Programmation/Motifs de conception

Un livre de Wikilivres.
Aller à : navigation, rechercher
Nuvola apps korganizer.svg
À faire...

Dans l'ordre :

  1. Finir la traduction (texte à traduire en commentaires)
  2. Compléter avec w:Motif de conception
  3. Déplacer les sections vers des sous-pages pour en faire un livre à part entière.
Translation arrow.svg
Demande de traduction

Cette page nécessite une traduction.
La page originale Computer_Science/Design_Patterns est en anglais. Si vous connaissez cette langue et le sujet de la page, vous pouvez poursuivre ou corriger la traduction.

Motifs de conception[modifier | modifier le wikitexte]

Introduction[modifier | modifier le wikitexte]

Le terme « motif de conception » (design patterns en anglais) peut sembler confus au premier abord, ou peut sembler difficile à utiliser, alors qu'en fait, il s'agit rien de moins qu'un moyen de réutiliser le code.

Les motifs de conception sont conçus une fois pour toute et évitent de revenir à leur conception, et sont nommés. Imaginez vous travaillant en équipe, et que quelqu'un essaye de vous expliquer que la classe qu'il vient d'écrire n'autorise qu'une seule instance. Au lieu de cela, cette personne aurait pu dire simplement : « La classe que je vient d'écrire est un singleton ».

Les motifs de conception peuvent être classés en différentes catégories dont les principales sont : motifs de création, motifs structurels et motifs de comportement.

Motifs de création[modifier | modifier le wikitexte]

Fabrique abstraite[modifier | modifier le wikitexte]

Définition
Une classe utilitaire qui crée une instance de plusieurs familles de classes. Elle peut également retourner une fabrique pour un certain groupe.

Monteur[modifier | modifier le wikitexte]

Définition
Sépare la construction d'un objet de sa représentation.

Fabrication[modifier | modifier le wikitexte]

Définition
Une classe utilitaire qui crée une instance d'une classe à partir d'une famille de classes dérivées.

Prototype[modifier | modifier le wikitexte]

Définition
Copie ou clone une classe existante au lieu de créer une nouvelle instance. Ce qui est utile au cas où créer une nouvelle instance d'une classe coûte davantage.

Singleton[modifier | modifier le wikitexte]

Le terme singleton fait référence à un objet qui ne peut être instancié qu'une seule fois. Dans les langages de programmation tel que Java, vous devez créer une instance d'un type d'objet (communément appelé classe) pour l'utiliser dans le code. Prenons le code suivant comme exemple :

 Animal chien;                  // Déclaration du type de l'objet
 chien = new Animal();          // Instanciation d'un objet

Ceci peut également s'écrire en une seule ligne pour économiser de la place :

 Animal chien = new Animal();   // Déclaration et instanciation

Souvent plusieurs instances d'un même type d'objet sont nécessaires. Vous pouvez créer plusieurs instances de la même classe, par exemple :

 Animal chien = new Animal();
 Animal chat = new Animal();

Maintenant que deux instances du même type d'objet ont été crées, il est possible d'utiliser les deux instances chien et chat séparément dans le programme. Toute modification faites à chien n'affectera pas l'instance chat car ces deux instances ont été créées dans deux espaces mémoire différents. Le code suivant montre que ces deux objets sont réellement différents :

 System.out.println(chien.equals(chat));  // affiche: false

Le code retourne false (faux) car les deux objets sont différents. Contrairement à cela, un singleton a un comportement différent. Un type d'objet singleton ne peut être instancié, mais il est possible d'en obtenir une instance. En utilisant Java, le code suivant montre la création d'un objet normal :

 class ObjetNormal {
     public ObjetNormal() {
     }
 }

Ce que nous faisons ici c'est créer une class (type objet) qui identifiera le type de nos objets. A l'intérieur des crochets il n'y a qu'une simple méthode avec le même nom que la class. Ce type de méthodes est appelée Constructor. Le constructeur est appelé a chaque "instanciation" de class. Pour instancier une class et par conséquent créer un objet ça n'est pas plus compliqué que ça.

 
 class TestHarness {
     public static void main(String[] args) {
          NormalObject object = new NormalObject();
     }
 }

Notice the constructor's accessor. This time around it has been declared private. Just by changing it to private, you have applied a great change to your object type. Now you can not instantiate the object type. Go ahead try out the following code.

 class TestHarness {
     public static void main(String[] args) {
          SingletonObject object = new SingletonObject();
     }
 }

The code returns an error because private class members can not be accessed from outside the class itself and in another class. This way you have disabled the instantiation process for an object type. However, you have to find a way of obtaining an instance of the object type. Let's do some changes here.

 class SingletonObject {
     private static SingletonObject object;
 
     private SingletonObject() {
        //Instanciate the object.
     }
 
     public static SingletonObject getInstance() {
         if (object == null) {
             object = new SingletonObject(); // Create the object for the first and last time
         }
         return object;
     }
 }

The changes involve adding a static class member called object and a public static method that can be accessible outside the scope of the class by using the name of the Class. To see how we can obtain the instance, lets code:

 class TestHarness {
     public static void main(String[] args) {
          SingletonObject object = SingletonObject.getInstance();
     }
 }

This way you control the creation of objects derived from your class. But we have still not unearthed the final and interesting part of the whole process. Try creating multiple instances and see what happens.

 class TestHarness {
     public static void main(String[] args) {
          SingletonObject object1 = SingletonObject.getInstance();
          SingletonObject object2 = SingletonObject.getInstance();
     }
 }

Unlike multiple instances of normal object types, multiple instances of a Singleton are all actually the same object instance. To validate the concept in Java, we try:

 System.out.println(object1.equals(object2)); // output: true

The code returns true because both object declarations are actually refering to the same object. So, in summarizing the whole concept, a Singleton can be defined as an object that can not be instantiated more than once. Typically it is obtained using a static custom implementation.

In some applications, it is appropriate to enforce a single instance of an object, for example: window managers, print spoolers, database access, and filesystems

Singleton et multi-thread[modifier | modifier le wikitexte]

Java utilise le concept multi-threads pour exécuter tout programme. Considérons la classe ObjetSingleton discutée précédemment. L'appel à la méthode getInstance() par plusieurs threads à n'importe quel moment peut créer deux instances de ObjetSingleton mettant le motif singleton en échec. Pour gérer plusieurs threads, deux solutions sont possibles :

  • Synchroniser la méthode getInstance(), ce qui garantit que l'appel à cette méthode ne peut être interrompu par un autre thread :
    public synchronized static ObjetSingleton getInstance()
    {
        if ( instance == null )
        {
            instance = new ObjetSingleton();
        }
        return instance;
    }
  • Créer l'instance à la déclaration, qui sera donc effectué au moment du chargement de la classe (donc avant tout appel de méthode):
 class ObjetSingleton
 {
     public final static ObjetSingleton object = new ObjetSingleton();
 
     private ObjetSingleton()
     {
        // Existe seulement pour éviter l'instantiation par une autre classe.
     }
 
     public static ObjetSingleton getInstance()
     {
         return ObjetSingleton.object;
     }
 }

Exemples[modifier | modifier le wikitexte]

Motifs structurels[modifier | modifier le wikitexte]

Adaptateur[modifier | modifier le wikitexte]

Utilisé pour changer l'interface d'une classe. It is a so called wrapper class.

Pont[modifier | modifier le wikitexte]

Objet composite[modifier | modifier le wikitexte]

C'est une classe composée de champs non primitifs (objets)

Décorateur[modifier | modifier le wikitexte]

Façade[modifier | modifier le wikitexte]

Une classe possèdant une méthode qui effectue un traitement complexe faisant appel à plusieurs autres classes.

Poids mouche[modifier | modifier le wikitexte]

Les informations partagées ne sont stockées qu'une seule fois.

Proxy[modifier | modifier le wikitexte]

Contrôle l'accès à un objet.

Motifs comportementaux[modifier | modifier le wikitexte]

Chaîne de responsabilité[modifier | modifier le wikitexte]

Commande[modifier | modifier le wikitexte]

Le motif commande est un motif comportemental d'objet qui découple envoyeur et receveur. On peut aussi le présenter comme l'équivalent orienté objet d'une méthode de rappel (call back method : une méthode enregistrée pour être appelée à un moment donné selon les actions de l'utilisateur).

 public interface Commande
 {
     public int execute(int a, int b);
 }
 
 public class CommandeAdditionne extends Command
 {
     public int execute(int a, int b)
     {
         return a + b;
     }
 }
 
 public class CommandeMultiplie extends Command
 {
     public int execute(int a, int b)
     {
         return a * b;
     }
 }
 
 public class TestCommand
 {
     public static void main(String a[])
     {
         Commande somme = new CommandeAdditionne();
         somme.execute(1,2); // retourne 3
         Commande produit = new CommandeMultiplie();
         produit.execute(2,3); // retourne 6
     }
 }

Dans l'exemple ci-dessus, on peut noter que le motif commande découple l'objet qui invoque l'opération et celui qui sait comment l'effectuer.


Interpréteur[modifier | modifier le wikitexte]

Itérateur[modifier | modifier le wikitexte]

Médiateur[modifier | modifier le wikitexte]

Ce motif aide à modéliser une classe dont l'objet est responsable du contrôle et de la coordination des interactions d'un groupe d'objets.

Mémento[modifier | modifier le wikitexte]

L'objet « origine » (l'objet à sauvegarder) crée un cliché de lui-même dans un objet « mémento » et passe sa référence à l'objet « gardien ». Cet objet « gardien » garde le « mémento » jusqu'à ce que l'objet « origine » ait besoin de retrouver l'état précédent enregistré dans l'objet « mémento ».

Observateur[modifier | modifier le wikitexte]

Ce motif défini une dépendance « un vers plusieurs » entre plusieurs objets telle qu'une modification de l'état de l'objet déclenche une notification à tous les objets dépendants afin qu'ils se mettent à jour.

État[modifier | modifier le wikitexte]

Ce motif autorise un objet à altérer son comportement quand son état interne change. L'objet parait changer de classe.

Stratégie[modifier | modifier le wikitexte]

Ce motif défini une famille d'algorithmes, encapsulant chacun, et chacun étant interchangeable. Le motif stratégie permet de varier l'algorithme utilisé indépendamment de celui qui l'utilise.

Patron de méthode[modifier | modifier le wikitexte]

Ce motif définit le squelette d'un algorithme en une opération, déléguant certaines étapes à des sous-classes. Un patron de méthode laisse le soin aux sous-classes de redéfinir certaines étapes de l'algorithme sans en changer la structure.

Visiteur[modifier | modifier le wikitexte]

Ce motif représente une opération à effectuer sur un élément d'une structure d'objet. Le motif visiteur permet de définir une nouvelle opération sans changer la classe des éléments sur lesquels il opère.

Autres Motifs[modifier | modifier le wikitexte]

Motif Modèle-Vue-Contrôleur[modifier | modifier le wikitexte]

Le motif Modèle-Vue-Contrôleur est un motif très commun qui partage un module en trois parties : Le modèle, la vue et le contrôleur. Le modèle est la représentation réelle des données (par exemple, tableau pour une liste chainée) ou d'autres objets représentant une base de données. La vue est une interface pour lire le modèle (implémentée par exemple en ASP (Active Server Page ou avec une interface client lourde). Le contrôleur (implémenté par exemple en Java avec des Servlets ou des EJB) fournit l'interface de modification des données et de sélection de la meilleure vue.


Newcommers will probably see this "MVC" model as wasteful, mainly because you are working with many extra objects at runtime, when it seems like one giant object will do. But the secret to the MVC pattern is not writing the code, but in maintaining it, and allowing people to modify the code without changing much else. Also, keep in mind, that different developers have different strengths and weakni, so team building around MVC is easier. Imagine a View Team that is responsible for great views, a Model Team that knows a lot about data, and a Controller Team that see the big picture of application flow, handing requests, working with the model, and selecting the most appropriate next view for that client.

Erm, someone please come up with a better example than the following... I can't think of any

For example: A naive central database can be organized using only a "model", for example, a straight array. However, later on, it may be more applicable to use a linked list. All array accesses will have to be remade into their respective Linked List form (for example, you would change myarray[5] into mylist.at(5) or whatever is equivalent in the language you use)

Well, if we followed the MVC pattern, the central database would be accessed using some sort of a function, for example, myarray.at(5). If we change the model from an array to a linked list, all we gotta do is change the view with the model, and the whole program is changed. Aka, keep the interfase the same but change the underworkings of it. This would allow us to make optimizations more freely and quickly than before.

Liens externes[modifier | modifier le wikitexte]