26 août 2016

Design patterns : This is the way

Design & Code

Marouane

El Haddaji

Image design pattern.

26 août 2016

Design patterns : This is the way

Design & Code

Marouane

El Haddaji

Image design pattern.

26 août 2016

Design patterns : This is the way

Design & Code

Marouane

El Haddaji

Image design pattern.


1 - Introduction



En premier lieu, les design patterns sont des modèles de conception répondant à des problématiques spécifiques dans la programmation orientée objet. Ils permettent aussi d'apporter des solutions efficaces, éprouvées par des développeurs experts dans le domaine et appliquées à des problèmes récurrents. Pourquoi réfléchir de zéro à un problème à chaque fois alors qu'il y a une solution existante à ce dernier ? De plus, ils facilitent la lecture du code par un autre développeur.



L’ouvrage qui a permis leur démocratisation est Design Patterns : Elements of reusable software, co-écrit par le Gang Of Four, composé des auteurs Gamma, Helm, Johnson et Vlissides. En effet, dans cet ouvrage, ils décrivent plus d'une vingtaine de design patterns qui sont classés sur trois catégories :



  • D'abord, les modèles de création "Creational design patterns"

  • Ensuite, les modèles de structuration "Structural design patterns"

  • Enfin, les modèles de comportement "Behavioral design patterns"



Cet article va donc aborder une sélection de design patterns les plus connus dans chacune de ces catégories pour mieux les appréhender.



2 - Design patterns : les modèles de création « Creational patterns »



Les modèles de création, qui concernent l’instanciation et
la configuration des classes et des objets, font appelles à deux concepts de la
POO qui sont l’héritage et la délégation. 



2.1     Singleton pattern



2.1.1      Problématique



Très souvent cité en entretien, le singleton pattern est un des modèles de design patterns le plus connu. Il répond en effet au besoin de n’avoir qu’une seule instance d’une classe et que cette dernière soit accessible dans toute l'application.



2.1.2      Exemple



Plus précisement, exemple basique du Singleton avec l’instance statique et la méthode statique pour la retourner.



2.1.2.1      Schéma



 

schéma de Singleton



2.1.2.2      Code






2.2     Builder pattern



2.2.1      Problématique



La construction d’une classe contenant plusieurs champs peut en effet être lourde à implémenter, surtout lorsque l’alimentation d’un certain champ dépend d’une logique métier complexe. Le Builder pattern consiste à déplacer cette logique de construction hors de la classe concernée afin de l’alléger et pour rendre plus modulable la construction de l’objet.



2.2.2      Exemple



Un produit avec des attributs qui est construit par une
classe Builder.



2.2.2.1      Schéma



 

schéma de Builder pattern



2.2.2.2 Code






2.3 Factory Method Pattern



2.3.1 Problématique



Dans les design patterns, le factory method pattern permet de créer des objets d’une même famille sans avoir à spécifier leur classe. Ce rôle est délégué à la Factory qui saura, à partir de certains paramètres, créer les objets de la bonne classe sans  exposer la logique de  leur création. De fait, c’est un pattern souvent utilisé dans les Frameworks et les librairies qui fournissent le contrat d’utilisation aux applications clientes.    



2.3.2 Exemple



Deux produits (TV, Radio) qui héritent d’une interface commune et qui sont construits par une classe Factory selon le type de produit.



2.3.2.1 Schéma



 

schéma de Factory Method Pattern



2.3.2.2 Code






3 - Design patterns : les modèles de structuration "Structural patterns"



3.1 Adapter



3.1.1 Problématique



Ce pattern permet, pour un client qui ne pourrait pas appeler directement les fonctionnalités d’un programme, d’utiliser une interface adaptée à ce dernier.



3.1.2 Exemple



Un adaptateur HDMI vers VGA où la classe « Adapter » implémente cette adaptation. 



3.1.2.1 Schéma



 

schéma de Structural pattern



3.1.2.2 Code






3.2 Bridge



3.2.1 Problématique



Le pattern du bridge permet de séparer la modélisation d’un problème à résoudre de son implémentation. Le problème est ainsi modélisé par une classe abstraite et une ou plusieurs classes représentent les implémentations possibles de cette problématique. Les implémentations peuvent donc évoluer et être changées en fonction des besoins sans avoir à modifier la modélisation du problème à résoudre.



3.2.2 Exemple



Un opérateur qui peut effectuer toutes les opérations qui implémentent l’interface « IOperation » en appelant la méthode « doOperation »



3.2.2.1 Schéma



 

schéma de Bridge



3.2.2.2 Code






3.3 Composite



3.3.1 Problématique



Le pattern du composite représente les objets de manière hiérarchisée sous forme d’une structure d’arbre et ces objets peuvent eux-mêmes être composés par d’autres objets afin qu’ils puissent être traités de manière uniforme.



3.3.2 Exemple



Un employé qui peut gérer zéro ou plusieurs employées.



3.3.2.1 Schéma



 

schéma de composite



3.3.2.2 Code



public class CompositePattern {
    interface IEmployee {
        int managedEmployeesCount();
        void add(IEmployee enmployee);
        void remove(IEmployee employee);
        void showInfo();
    }
    class Employee implements IEmployee {
        String firstName;
        String lastName;
        List<IEmployee> employees = new ArrayList<>();
        @Override
        public int managedEmployeesCount() {
            return employees.size();
        }
        @Override
        public void add(IEmployee employé) {
            employees.add(employé);
        }
        @Override
        public void remove(IEmployee employé) {
            employees.remove(employé);
        }
        @Override
        public void showInfo() {
            System.out.println("Employee{" +
                    "firstName='" + firstName + '\'' +
                    ", lastName='" + lastName + '\'' +
                    ", number of managed employees=" + employees.size() +
                    '}');
            Iterator<IEmployee>



4 - Design patterns : les modèles de comportement "Behavioral patterns"



4.1 Observer



4.1.1 Problématique



Le pattern Observer répond au besoin des clients de suivre le changement d’état d’un objet afin de se mettre à jour. En effet dans ce pattern, un «Subject » est observé par des « Observers » qui s’enregistrent auprès de lui et qui seront notifiés de toutes les modifications.



4.1.2 Exemple



Un article « Subject » qui est suivi par plusieurs lecteurs « Observers » où lorsqu'il est modifié, les lecteurs seront alors notifiés.



4.1.2.1 Schéma



 

Schéma de Behavioral pattern



4.1.2.2 Code



public class ObserverPattern {
    interface Subject {
        void register(Observer observer);
        void notifyObservers();
        void unregister(Observer observer);
    }
    interface Observer {
        void update();
        void setSubject(Subject subject);
    }
    class Article implements Subject {
        List<Observer>



4.2 State



4.2.1 Problématique



Là-dessus, l'’état d’un objet est déterminé par le changement de valeurs de ces attributs. Le State pattern permet donc à l’objet de changer son comportement quand un changement survient sur son statut interne.



4.2.2 Exemple



Un moteur qui peut être démarré ou à l’arrêt.



4.2.2.1 Schéma



 

schéma de State



4.2.2.2 Code






4.3 Strategy



4.3.1 Problématique



Un objet client a en effet besoin de choisir dynamiquement un algorithme adapté à la problématique qu’il traite. Alors le strategy pattern permet d’encapsuler chaque algorithme dans une classe d’implémentation et de pouvoir utiliser la plus adaptée pour résoudre un problème.



4.3.2 Exemple



Un exemple de jeu où il y a plusieurs stratégies notamment celle d’attaque ou de défense.



4.3.2.1 Schéma



 

schéma de Strategy



4.3.2.2 Code






Pour conclure sur le sujet des design patterns, il n’y a donc plus que le pattern du Singleton à citer dans un prochain entretien. Essentiellement, la manière la plus efficace pour les retenir c’est la pratique dès que l’occasion se présente, n’hésitez pas à les utiliser !



Poursuivez votre lecture sur nos autres articles autour de Java !