Canalblog
Suivre ce blog Administration + Créer mon blog

Developpement Web en Java

17 septembre 2007

Javascript. Modelisation objet

Avec l'avènement de l'AJAX, javascript est devenu incontournable pour developper des page plus user frend. Le developpement classique des scripts comme on le faisait ne peut plus repondre a la complexite de plus en plus grandissante  des scripts. Il faut donc apprendre les bests pratice de developpement.

Je partage donc des techniques que j'ai mis en oeuvre via le javascript

//////////////////////////////////////////////////////////////////////////////////////////
//Objet Etudiant

var Etudiant=function(){
    this.nom="sere";
    this.prenom="brahima";
    this.inscrire=function(){
        alert(this.nom+" "+this.prenom+" est maintenant inscrit");
    }

}

//Instanciation d'un nouvel objet
moussa=new Etudiant();
moussa.inscrire();

//////////////////////////////////////////////////////////////////////////////////////////
//Objet Ecole avec paramètre passé a son constructeur

var Ecole=function(nomEco){
    this.nomEcole=nomEco;
    this.autorise="non";
    this.donnerAutorisation=function(){
        this.autorise="oui";
        alert(this.nomEcole+" est maintenant autorise par l'etat");
    }
}
//instancier
lavigeri=new Ecole("lavigeri");
lavigeri.donnerAutorisation();

//Ce code ci dessous en commenaire génère une erreur puisse que la fonction n'existe.
//lavigeri.changerQuartier('dassasgo')
//On peut ajouter cette methode via le mecanisme d'extension par prototype

/**/////////////////////////////////////////////////////////////////////////////////////////
//    Extension de la classe Ecole

//ajouter l'attribut quartier a ecole
Ecole.prototype.quartier='bolomakote';
//Ajouter la méthode changerQuartier
Ecole.prototype.changerQuartier=function(newQuartier){
    this.quartier=newQuartier;
    alert("Le nouveau nom du quartier est "+this.quartier);
}
//Ce code est maintenant possible grace de l'ajout de la methode via le prototype
lavigeri.changerQuartier('dassasgo');

//Creation d'une nouvel ecole
maricuri=new Ecole('maricuri');
maricuri.changerQuartier('kilwin');

//NB.
/* On ne peut pas surcharger une methode qui a été définie
dans le corps d'une classe à l'exterieure par le mécanisme de prototype.
Cela genere une erreur
/*Le code suivant est incorrect, car donnerAutorisation a ete definie a l'interieur
de la fonction.

Ecole.prototype.donnerAutorisation=function(str){
alert(str);
}
maricuri.donnerAutorisation("ja changer sa definition");

Par contre il est possible de redefinir changerQuartier car defini dans un prototype
*/

/**/////////////////////////////////////////////////////////////////////////////////////////
//   METHODE STATIQUE  et METHODE D'INSTANCE

//Declarons la methode getPays comme methode d'instance
Ecole.getPays=function(){
    alert("BF. pays de toutes les ecoles");
}
//On remarque que la declaration diverge par l'absence du mot cle prototype
Ecole.getPays();
//lavigeri.getPays(); Cette ligne est erronee. la methode est statique

//declarons une methode d'instance pour lavigeri (seul lavigeri verra cette methode);
lavigeri.getFondateurLavigeri=function(){
    alert("le fondateur de lavigeri est papa sinco");
}

lavigeri.getFondateurLavigeri();

//maricuri.getFondateurLavigeri(); Cette ligne et erronee. maricuri ne possede pas de methode getFondateurLavigeri

/**/////////////////////////////////////////////////////////////////////////////////////////
//   HERITAGE METHODE 1

//Supposons que l'on ait une classe EcoleNoire qui herite de ecole et qui represente l'ensemble
//des mauvaises ecoles. Pour definir l'heritage faire

var EcoleNoire=function(nomEco,raisonMauvaisCl){
    Ecole.call(this,nomEco);//permet d'initialiser les attributs de la mere
    this.raisonBadClassement=raisonMauvaisCl;
}

ecoleDuSud=new EcoleNoire("ecole du sud","mauvais resultat");
ecoleDuSud.donnerAutorisation();

//ecoleDuSud.changerQuartier("ecole du sud"); Cette ligne est erronee
//en effet la classe fille n'hérite pas des éléments de la classe défini au niveau de son
//prototyepe

/**/////////////////////////////////////////////////////////////////////////////////////////
//   HERITAGE METHODE 2
EcoleExcellence=function(nomEco,raisonExcellence){
     Ecole.call(this,nomEco);//Cette ligne n'est pas necessaire pour implementer l'heritage avec la deuxieme methode. C'est seulement qu'avec cette methode, les attributs de la classe meres ne sont pas initialise. il faut donc faire ca pour y arriver. On peut toujours initialiser à l'exterieur de la fonction
    this.raisonBonClassement=raisonExcellence;
}
EcoleExcellence.prototype = new Ecole();
lyceeClassique=new EcoleExcellence("lycee classique","bon resultat");
lyceeClassique.donnerAutorisation();

/**/////////////////////////////////////////////////////////////////////////////////////////
//   HERITAGE METHODE 3
function heriter(destination, source){
    for(var element in source){
        destination[element]=source[element];
    }
}

function EcoleFermee(nomEco,raionFerm){
    this.nomEcole=nomEco;
    this.raisonFermeture=raionFerm;
}
heriter(EcoleFermee.prototype,Ecole.prototype);
var gandjaEcole=new EcoleFermee("gandja ecole","consommation drogue");
gandjaEcole.changerQuartier('gandja citi');
//gandjaEcole.donnerAutorisation();// Declaration erronee car cette methode n'est pas dans un prototype mais dans le corps de la fonction

/**/////////////////////////////////////////////////////////////////////////////////////////
//   HERITAGE METHODE 4.    COMBINER LES STRATEGIES
function EcoleArt(nomEco,typeArt,nbreEtu){
    this.nomEcole=nomEco;
    this.typeArt=typeArt;
    this.nbreEtu=nbreEtu;
}
EcoleArt.prototype={
    getSpecialite:function(){
        alert("specialite musique");
    }
}
heriter(EcoleArt.prototype,Ecole.prototype);
var ecoleMusiqueAward=new EcoleArt("musique award","musique",17);
ecoleMusiqueAward.getSpecialite();
ecoleMusiqueAward.changerQuartier("quartier koko");
lavigeri.donnerAutorisation();//ceci est maintenant ok. il a acces a tout
//L'inconvenient de cette methode, c'est qu'il ne permet pas de metre en oeuvre le
//polymorphisme

/**/////////////////////////////////////////////////////////////////////////////////////////
//    LE POLYMORPHISME
var obj_1=new Object();
alert("objet de type Object :"+(obj_1 instanceof Object ));

alert("lavigeri de type Ecole :"+(lavigeri instanceof Ecole ));
alert("lavigeri de type EcoleNoire :"+(lavigeri instanceof EcoleNoire ));

/**
Heritage avec Methode 1 (Initisation par constructeur) : ne supporte pas le polymorphisme
*/
alert("ecoleDuSud de type EcoleNoire :"+(ecoleDuSud instanceof EcoleNoire ));
alert("ecoleDuSud de type Ecole :"+(ecoleDuSud instanceof Ecole ));

/**
Heritage avec methode 2 (prototype) :supporte le polymorphisme
*/
alert("lyceeClassique de type EcoleNoire :"+(lyceeClassique instanceof Ecole  ));
alert("lyceeClassique de type Ecole :"+(lyceeClassique instanceof EcoleExcellence ));

/**
Heritage avec methode 3 (copie par la fonction heriter) :ne supporte pas  le polymorphisme
*/
alert("gandjaEcole de type EcoleFermee :"+(gandjaEcole instanceof EcoleFermee ));
alert("gandjaEcole de type Ecole :"+(gandjaEcole instanceof Ecole  ));

/**
Heritage avec strategie 4 (copie par la fonction mixage methode) :ne supporte pas  le polymorphisme
*/
alert("ecoleMusiqueAward de type EcoleArt :"+(ecoleMusiqueAward instanceof EcoleArt ));
alert("ecoleMusiqueAward de type Ecole :"+(ecoleMusiqueAward instanceof Ecole  ));

/**/////////////////////////////////////////////////////////////////////////////////////////
//    CLASSE ABSTRAITE
/**
    Une classe abstraite est une classe qui possède une méthode utilisable dans cette même classe et dont le corps n'a pas été défini dans la classe. Pour illustrer notre propos nous allons definir une classe Mammifere  qui aurra des sous classes qui vont redefinir son comportement

*/
var Mammifere=function(modeAccouchement){
    this.modeAccouchement=modeAccouchement;
}
Mammifere.prototype={
    seNourrir:function(){
        this.manger();
    },
    manger:function(){//methode abstraite non encore implémentee
        throw new Error("non implémentée!"); 
    }
}
//Une classe fille Animal
var Animal=function(modeAccouch){
    this.modeAccouchement=modeAccouch;
}
heriter(Animal.prototype, Mammifere.prototype);
Animal.prototype.manger=function(){ 
    alert("manger avec la bouche");   
}
lion=new Animal("tombe enceinte");
lion.seNourrir();

//Une classe fille EtreHumain

var EtreHumain=function(modeAccouch){
    this.modeAccouchement=modeAccouch;
}
heriter(EtreHumain.prototype, Mammifere.prototype);
EtreHumain.prototype.manger=function(){ 
     alert("manger par la main");   
}
rene=new EtreHumain("tombe enceinte");
rene.seNourrir();

/**/////////////////////////////////////////////////////////////////////////////////////////
//    MOT CLE THIS

//ATTACHEMENT D'UNE METHODE A PLUSIEURS OBJETS
//On peut attacher une meme fonction a deux objets qui vont s'executer dans des contextes différents. Soit l'exemple qui suit
function montrerQuartier(){
    alert(this.quartier);
}
Ecole.prototype.afficheQuartier=montrerQuartier;
lavigeri.afficheQuartier();

EcoleFermee.prototype.afficheQuartier=montrerQuartier;
gandjaEcole.afficheQuartier();

//NB: On voit bien que la methode s'execute dans le contexte de l'objet

//PASSAGE DE METHODES DOBJECTS A UNE AUTRE FONCTION
/**
Un des problèmes que l'on fait face dans la POO, est le passage de methodes d'objets a
une autre fonction.
-----Mais quel est le problème :
Pour le cas de methode d'une classe, elle necessite d'etre utilise par un objet puisse qu'elle mette en oeuvre le mot cle this. Or javascript ne permet que de referencer des fonctions. donc si on passe la methode d'un objet a une fonction, c'est ce contexte de la
fonction qui sera utilisee. Ainsi les methodes seront executees hors contexte de l'objet.
Les elements references par le mot cle this ne seront pas resolus.
------Ainsi l'exemple qui illuste bien ce probleme
*/

Mammifere.prototype.decrireAccouchement=function(){
        alert("mon mode d'accouhement :"+this.modeAccouchement);
    }

phoenix=new Mammifere("accouche par les cendres");

function afficherModeAccouchement(fonction){
    fonction();
}

afficherModeAccouchement(phoenix.decrireAccouchement); //le mode accouchement ne pourra pas etre lu

// --- Comment resoudre le probleme
/**
L'astuce consiste en l'utilisation d'une closure pour la méthode afin de creer une fonction
réalisant l'execution de la méthode dans le contexte de son objet. les framework comme Prototype et Dojo on des methodes du genre (Prototype.bind et dojo.lang.hitch
*/
function bind(objet, methode) {

    return function() {

        return methode.apply(objet, arguments);

    }

}
//apply est une methode de l'objet Function qui permet d'executer une fonction dans le contexte d'un objet(premier argument),en lui passant des paramètres en entree (second argument)
//
afficherModeAccouchement(bind(phoenix,phoenix.decrireAccouchement));

/**/////////////////////////////////////////////////////////////////////////////////////////
//    DESIGN PATTERN
//Dans le tuto 3

//OBSERVATEUR
//Fonction permettant d'enregistrer un observateur sur un objet
function enregistrerObservateur(objet, methode, observateur) {

    var objMethode = objet[methode];

    objet[ "__" +  methode] = objMethode;

    objet[methode] = function() {

        observateur();

        objMethode.apply(this, arguments);

    }

}
enregistrerObservateur(lavigeri,"afficheQuartier",function(){
        alert("je m'execute avant un appel de la methode afficher quartier de lavigeri.");
    }
);

lavigeri.afficheQuartier();
/**/////////////////////////////////////////////////////////////////////////////////////////
//    NAMESPACE
//Les namespaces sont une facon de definir les packages a l'interieur duquel on aura des methodes, des objets etc. On peut ainsi decider de rendre publique ce que l'on veut
//Pour simuler ce fonctionnement, on combine closure et forme litterale a la json
var DOMX=window.DOMX || {};
DOMX=function(){
    var moveComponent=function(){//Cette fonction n'est visible que dans le package
        alert("deplacement de composant");
    };
    return{
        init:function(){
            alert("initialisation");
            moveComponent.apply(null,arguments);
        },
        rien:function(){
            alert("rien a l'horizon");
        }
    }
}();

//Execution de l'initialisation
DOMX.init();
DOMX.rien();
//OUEDX.moveComponent();//erreur n'est pas visible

//On peut combiner tout ca pour avoir un exemple plus complexe.

//L'exemple ci dessous creer une methode init qui pourra etre appele comme cela :

//OUEDX.Utils.init();

//Debut paquetage OUEDX
var OUEDX=window.OUEDX || {};

OUEDX.Utils=function(){
        var fonccombo=function(){
        }
        fonccombo.prototype.afficherCombo=function(){
            alert("mon combo est affiche");
        }
    //public pour OUEDX.Utilities
    return{
        init:function(){
            alert("init du combo");
        }
    }
     ////////////////////////////////////Fin packetage OUEDX.Utils
}();

OUEDX.Utils.init();

Publicité
Publicité
17 avril 2007

Java open Source

Enfin c'est arrivé. Java est dévenu open source. Longtemps restant dans le giron des logiciels propriétaires, il a enfin franchi le pas. Java sera sous licence GPL. La licence GPL etant virale (Inclure des bibliothèques GPL dans un projet oblige à mettre ce projet sous GPL, donc à ouvrir son code), java a inclu une close de Classpath permettant à tous de l'intégrer sans avoir à ouvrir son code.

Encodre merci à sun qui a su faire le bon choix.

Publicité
Publicité
Developpement Web en Java
Publicité
Publicité