Editer Design patterns
Ou "patrons de conception", "modèles de conception". Façons types, éprouvées, d'organiser le code pour le rendre plus évolutif, maintenable etc. Ce sont des idées de conceptions générales.
Factory Method
Patron basé sur l'héritage :
-une factory (usineDAnimaux) et des factories qui héritent de son type (usine de Chien, de Chat...).
-un produit (Animal) et des produits qui en hérite (Chien, Chat).
-dans l'usine mère, des méthodes qui utilisent le produit (sans se soucier de son sous type).
Quand utiliser ?
-Quand on pense que notre type risque d'être étendu et qu'on ne veut pas avoir à tout modifier.
-Un peu pareil, quand on veut laisser les utilisateurs de notre programme étendre (typiquement un framework) ET utiliser ce qu'il nous donne. Typiquement le framework appelle la méthode presserBouton(Bouton) dans BoutonFactory et on peut lui donner un MonBoutonTresJoliBoutonFactory.
-Comme toutes les factories, quand l'objet est un peu reloud à initialiser (connexion en BDD etc) mais il faut que ça se justifie par les 2 points au dessus aussi.
Comment l'utiliser ?
-On utilise la classe parent.
class Main {
public static void main(String[] args) {
run(new UsineDeChien()); //Supppeer pratique, on a juste à remplacer par usineDeChat et tout marche encore.
}
public static void run(UsineDAnimaux usine) {
usine.petAnimalInShelter();
}
}
abstract class UsineDAnimaux {
protected abstract Animal creerAnimal(); // La factory method
public void petAnimalInShelter() { // Elle utilise des produits
(creerAnimal()).caresser();
}
}
class UsineDeChien extends UsineDAnimaux {
@Override
protected Animal creerAnimal() { return new Chien(); }
}
class Animal {
public void caresser() {
System.out.println("Grr...");
}
}
class Chien extends Animal{
public void caresser() {
System.out.println("Ouaf !");
}
}
Ne pas confondre avec :
-Simple Factory (une méthode qui génère un objet mais sans ces notions d'héritage etc).
-Abstract Factory (une interface/classe UsineDAnimaux abstraite qui contient plusieurs méthodes gens creerChien(), creerChat() puis serait implémenté par des factories UsineDAnimauxSansPoils, UsineDAnimauxMecaniques...).
Abstract Factory
Pattern noté comme basé sur la composition (même si l'héritage est nécessaire pour construire ce pattern).
-Une factory interface/class abstraite UsineDAnimaux qui sera implémenté par des factories concrète UsineDAnimauxSansPoils, UsineDAnimauxMecaniques...).
-Dans les factories concrètes, plusieurs méthodes gens creerChien(), creerChat().
-Les factories n'ont PAS de code métier.
Quand utiliser ?
-Quand on a des collections d'objets de la même "famille".
-Quand on veut éviter de mélanger des objets.
Gros défaut :
Compliquer d'ajouter un produit, il faut l'ajouter aprtout (oiseauMecanique, oiseauSansPoil...).
Pourquoi "composition" ?
-C'est le classement qu'on trouve souvent mais c'est un peu foireux car ça ressemble beaucoup à la Factory Method avec une usine en polymorphe avec laquelle on créé des objets polymorphe. La grosse différence avec la Factory Method c'est qu'on appelle nous même la méthode de création (fabrique.createCat()) et une méthode dans l'objet qu'on vient de fabrique, donc le client en sait un peu plus que dans la Factory Method. Souvent la classe qui utilise la fabrique va garder la fabrique en attribut donc bon voilà c'est classé comme ça.
class Main {
public static void main(String[] args) {
caresserTouteLaFamille(new FabriqueAnimauxMecaniques()); //on pourrait imaginer qu'on garde la fabrique en attribut
caresserTouteLaFamille(new FabriqueAnimauxSansPoils());
}
static void caresserTouteLaFamille(FabriqueAnimaux fabrique) { // Ici on caresse la même "famille" de chats et de chiens
fabrique.createCat().caresser(); //On appelle le code métier direct dans la classe.
fabrique.createDog().caresser();
}
}
abstract class Animal { abstract void caresser(); }
abstract class Chat extends Animal {}
abstract class Chien extends Animal {}
interface FabriqueAnimaux { Chat createCat(); Chien createDog(); }
class FabriqueAnimauxMecaniques implements FabriqueAnimaux {
public Chat createCat() { return new ChatMecanique(); }
public Chien createDog() { return new ChienMecanique(); }
}
class FabriqueAnimauxSansPoils implements FabriqueAnimaux {
public Chat createCat() { return new ChatSansPoils(); }
public Chien createDog() { return new ChienSansPoils(); }
}
class ChatMecanique extends Chat { void caresser() { System.out.println("La peau du chat est métallique."); } }
class ChienMecanique extends Chien { void caresser() { System.out.println("La peau du chien est métallique"); } }
class ChatSansPoils extends Chat { void caresser() { System.out.println("La peau du chat est sans poils"); } }
class ChienSansPoils extends Chien { void caresser() { System.out.println("La peau du chien est sans poils"); } }