Skip to content

Flyweight design pattern description / Description du design pattern Poids Mouche

Notifications You must be signed in to change notification settings

choubidouap/flyweight

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 

Repository files navigation

🍃 Flyweight - Poids mouche 🍃

La page est longue car à la fin il y a des exemples de codes.

Les problèmes à résoudre

La création d'objet prend du temps. On est d'accord, à chaque nouvel objet il faut exécuter tout le code correspondant. Le problème c'est que l'exécution de ce code peut prendre du temps. On ne parle peut-être pas de minutes, mais même quelques millisecondes on déjà un impacte.

Un autre problème est celui du stockage. Chaque objet occupe de l'espace en mémoire. Il faut donc faire attention à bien gérer l'espace mémoire occupé par nos objets, histoire de ne pas en être à court un jour.

Intentions du pattern

Réduire l'espace mémoire utilisé par les objets

Réduire les dépenses en termes de calculs

Gagner du temps d'éxécution pour notre application

Comment ?

Partager, autant que possible, des données similaires entre plusieurs objets.

  • Données intrinsèques: dépendent de l'objet en question

  • Données extrinsèques: ne dépendent pas de l'objet en question

On va donc faire en sorte que les objets partagent entre eux des données extrinsèques.

Exemple: Les Strings

C'est typiquement ce qu'il arrive avec les objets String. Je pense que nous sommes d'accord sur le fait que deux variables contenant la même String (même suite de caractère) pointent sur le même objet String.

public class PoidsMoucheString {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        
        String s1 = "test";
        String s2 = "foo";

       // Affichage
        System.out.println(s1 + " hashcode : " + s1.hashCode() );
        System.out.println(s2 + " hashcode : " + s2.hashCode() );

       System.out.println("##################");

       // On change ici la valeur de la chaîne
        s2 = "test"; // on assigne "test" à la variable s2
        System.out.println(s1 + " hashcode : " + s1.hashCode() );
        System.out.println(s2 + " hashcode : " + s2.hashCode() );
        // On se rend compte que les 2 variables pointent sur le même objet 
    }   
}

Quand utiliser ce design pattern ?

  • Lorsque nous avons beaucoup d'objets dans notre application.

  • Lorsque les coûts en stockage sont élevés.

  • Les objets possèdent des mêmes caractéristiques. (ils pourront donc se partager des données)

  • L'application n'a pas besoin d'objet unique.

  • ‼️ Ne pas utiliser si l'information partagée peut varier à travers le temps ‼️


Diagramme de séquence diagramme de séquence du poids mouche


Exemple: Créations d'arbres

Admettons que dans notre application nous voulons créer des arbres identiques. Les seules choses qui les différencient sont leurs positions X et Y.

  • Nos données extrinsèques seront les données relatives à l'aspect visuels des arbres.
  • Nos données intrinsèques seront les données de positions. Ces donnée sont propres à chaques arbres.
import java.util.Arrays;
public class PoidsMoucheSimple {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws InterruptedException {

        Arbre monArbre = new Arbre(10, 32);
        Arbre monDeuxiemeArbre = new Arbre(0, 2);
        
        // Regardons si les deux arbres on bien les mêmes feuilles
        System.out.println(monArbre.lesFeuilles); // check l'adresse du tableau
        System.out.println(Arrays.toString(monArbre.lesFeuilles)); // check l'adresse de chaque feuille
        monArbre.getCoordonnees();
        System.out.println(monDeuxiemeArbre.lesFeuilles); // check l'adresse du tableau 
        System.out.println(Arrays.toString(monDeuxiemeArbre.lesFeuilles)); // check l'adresse de chaque feuille
        monDeuxiemeArbre.getCoordonnees();
        
        // Dorénavant, n'importe quel arbre qui sera crée pointera sur le même
        // tableau tout en ayant ses propres propriétés x et y.*/
   }
}
class Feuilles {
    private final int feuilles;
    
    public Feuilles() throws InterruptedException{
        this.feuilles = 1;
        System.out.println("Je genère une feuille");    
        Thread.sleep(1000); // simule le fait que ça prend du temps
    }
}
class Arbre {
    private static Feuilles[] feuilles;
    public Feuilles[] lesFeuilles; // En public juste pour tester l'adresse dans le main
    private Feuilles[] desFeuilles; // intérmédiaire, utilisé une fois pour la méthode getFeuilles(
    private int x;
    private int y;
    
    public Arbre(int leX, int leY) throws InterruptedException{
        // Il faut créer les Feuilles ici
        if (feuilles != null){
            // les Feuilles ont déjà étée crée
            this.lesFeuilles = feuilles;
        } else {
            // il faut créer les Feuilles (arrivera que lors de la création du premier arbre)
            feuilles = getFeuilles();
            this.lesFeuilles = feuilles;
        } 
        this.x = leX;
        this.y = leY;
        System.out.println("Un arbre apparaît.");
    }
    
    public Feuilles[] getFeuilles() throws InterruptedException{
        desFeuilles = new Feuilles[10];
        for(int i = 0 ; i < 10 ; i ++){
            desFeuilles[i] = new Feuilles();
        }
        return desFeuilles;
    }
    
    public void getCoordonnees(){
        System.out.println("En x: " + this.x + " | En y: " + this.y);
    }
}

Exemple: Créations d'arbres, version Avancée

Ici on utilise aussi la Factory. On ne gère pas la position x et y. La seule chose qui change entre les arbres est leur taille.

import java.util.Arrays;
/**
 * FLYWEIGHT - POIDS MOUCHE
 * DESIGN PATTERN
 * @author choubidouap
 */
public class PoidsMoucheAvance {
    /**
     * @param args the command line arguments
     * @throws java.lang.InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Arbre[] arbres;
        int nombreArbres;
        
        // Combien d'arbres seront génerés
        nombreArbres = 100000;
        // set la taille du tableau
        arbres = new Arbre[nombreArbres];
        // Générer le nombre d'arbre choisis
        for (int i = 0 ; i < nombreArbres ; i ++){
            arbres[i] = ArbreFactory.getArbre(getRandomTaille()); // ici on cale un random
        }
        
        System.out.println("Nombres d'arbres: " + arbres.length);
        System.out.println("Nombres d'objets arbre: " + ArbreFactory.nombreObjets());
        
/*--------- TESTS POUR CONSTATER LE FONCTIONNEMENT DU FLYWEIGHT ---------*/
       // test les feuilles
        System.out.println(Arrays.toString(arbres[5].lesFeuilles));
        System.out.println(Arrays.toString(arbres[120].lesFeuilles));
        System.out.println(Arrays.toString(arbres[32].lesFeuilles));
        System.out.println(Arrays.toString(arbres[82].lesFeuilles));
        // test les arbres
        System.out.println(Arrays.toString(arbres));
    }
    
    // Taille minimum et maximum des arbres
    static int tailleMin = 20; // compris
    static int tailleMax = 27; // non-compris
    /**
     * Génère un chiffre aléatoire compris entre un maximum et minimum spécifié
     * @return le chiffre généré 
     */
    private static int getRandomTaille() {
       return (int)(Math.random() * (tailleMax-tailleMin)) + tailleMin;
    }
}
class Feuilles {
    private final int feuilles;
    
    public Feuilles() throws InterruptedException{
        this.feuilles = 1; // Juste du remplissage
        System.out.println("Je genère une feuille");
        Thread.sleep(500); // Simuler un temps d'éxectution long (en millisecondes)
    }
}
public class ArbreFactory {
    // La clé sera la taille de l'arbre
    private static final HashMap<Integer, Arbre> arbresMap = new HashMap();
    
    /**
     * Va transmettre un arbre de la taille demandée. Le créera s'il n'existe pas encore. 
     * @param taille
     * @return un arbre de la taille correspondante
     * @throws InterruptedException 
     */
    public static Arbre getArbre(int taille) throws InterruptedException{
        if(arbresMap.containsKey(taille)){ // Si un arbre de la taille correspondante existe
            System.out.println("Cet arbre existe.");
            return arbresMap.get(taille); // on retourne l'arbre correspondant
        } else {
            // Cet arbre n'existe pas, alors on le crée et on le met dans le HashMap            
            System.out.println("Un arbre est créé.");
            arbresMap.put(taille, new Arbre(taille)); // création de l'arbre et ajout dans le HashMap
            return arbresMap.get(taille); // on retourne l'arbre correspondant
        }
    }
    
    public static int nombreObjets(){
        return arbresMap.size();
    }
}
class Arbre {
    private static Feuilles[] feuilles;
    public Feuilles[] lesFeuilles; // En public juste pour tester l'adresse dans le main
    private int taille;
    
    /**
     * Crée un arbre de la taille définie en argument
     * @param laTaille
     * @throws InterruptedException 
     */
    public Arbre(int laTaille) throws InterruptedException{
        // Test pour savoir si des feuilles ont déjà été créée
        if (feuilles != null){
            // les Feuilles ont déjà étée créée
            this.lesFeuilles = feuilles;
        } else {
            // il faut créer les Feuilles (arrivera que lors de la création du premier arbre)
            feuilles = getFeuilles();
            this.lesFeuilles = feuilles;
        } 
        this.taille = laTaille;
        Thread.sleep(2000);
    }
    
    /**
     * Va créer des feuilles
     * @return
     * @throws InterruptedException 
     */
    public Feuilles[] getFeuilles() throws InterruptedException{
        Feuilles[] desFeuilles;
        int nombreFeuilles = 10;
        
        desFeuilles = new Feuilles[nombreFeuilles];
        for(int i = 0 ; i < nombreFeuilles ; i ++){
            desFeuilles[i] = new Feuilles();
        }
        return desFeuilles;
    }
    
    public void getCoordonnees(){
        System.out.println("Taille de l'arbre: " + this.taille);
    }
}

Les projets et le pdf de ce documents sont sur le drive. Bises.

About

Flyweight design pattern description / Description du design pattern Poids Mouche

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published