Mon point de vue sur le sujet.
Les quatre modèles ont beaucoup en commun, tous les quatre sont parfois appelés de manière informelle wrappers ou wrapper patterns. Tous utilisent la composition, enveloppant le sujet et déléguant l'exécution au sujet à un moment donné, mappent un appel de méthode à un autre. Ils épargnent au client la nécessité de devoir construire un objet différent et de copier toutes les données pertinentes. S'ils sont utilisés à bon escient, ils économisent de la mémoire et du processeur.
En favorisant le couplage lâche, ils rendent le code autrefois stable moins exposé aux changements inévitables et mieux lisible pour les autres développeurs.
Adaptateur
L'adaptateur adapte le sujet (adaptee) à une interface différente. De cette façon, nous pouvons ajouter un objet à placer dans une collection de types nominalement différents.
L'adaptateur expose uniquement les méthodes pertinentes au client, peut restreindre toutes les autres, révélant des intentions d'utilisation pour des contextes particuliers, comme l'adaptation d'une bibliothèque externe, la faisant apparaître moins générale et plus axée sur les besoins de notre application. Les adaptateurs améliorent la lisibilité et l'auto-description de notre code.
Les adaptateurs protègent une équipe du code volatil des autres équipes; un outil de sauvetage quand il s'agit d'équipes offshore ;-)
Moins mentionné, il vise à empêcher la classe de matière d'un excès d'annotations. Avec autant de frameworks basés sur des annotations, cela devient plus important que jamais.
L'adaptateur permet de contourner la limitation Java de l'héritage unique. Il peut combiner plusieurs adaptations sous une seule enveloppe donnant une impression d'héritage multiple.
En ce qui concerne le code, l'adaptateur est «mince». Il ne devrait pas ajouter beaucoup de code à la classe adaptee, en plus d'appeler simplement la méthode adaptee et des conversions de données occasionnelles nécessaires pour effectuer de tels appels.
Il n'y a pas beaucoup de bons exemples d'adaptateurs dans JDK ou dans les bibliothèques de base. Les développeurs d'applications créent des adaptateurs pour adapter les bibliothèques aux interfaces spécifiques à l'application.
Décorateur
Le décorateur non seulement délègue, mappe non seulement une méthode à une autre, il en fait plus, il modifie le comportement de certaines méthodes de sujet, il peut décider de ne pas appeler la méthode de sujet du tout, de déléguer à un autre objet, un objet d'aide.
Les décorateurs ajoutent généralement (de manière transparente) des fonctionnalités à l'objet encapsulé comme la journalisation, le chiffrement, le formatage ou la compression du sujet. Cette nouvelle fonctionnalité peut apporter beaucoup de nouveau code. Par conséquent, les décorateurs sont généralement beaucoup plus «gros» que les adaptateurs.
Le décorateur doit être une sous-classe de l'interface du sujet. Ils peuvent être utilisés de manière transparente au lieu de ses sujets. Voir BufferedOutputStream, il s'agit toujours de OutputStream et peut être utilisé comme tel. C'est une différence technique majeure par rapport aux adaptateurs.
Des exemples de manuels de toute la famille des décorateurs sont facilement disponibles dans JDK - Java IO. Toutes les classes comme BufferedOutputStream , FilterOutputStream et ObjectOutputStream sont des décorateurs de OutputStream . Ils peuvent être en couches d'oignon, où un décorateur est à nouveau décoré, ajoutant plus de fonctionnalités.
Procuration
Le proxy n'est pas un wrapper typique. L'objet encapsulé, le sujet proxy, peut ne pas encore exister au moment de la création du proxy. Le proxy le crée souvent en interne. Il peut s'agir d'un objet lourd créé à la demande, ou d'un objet distant dans une JVM ou un nœud de réseau différent et même un objet non Java, un composant en code natif. Il n'a pas besoin d'envelopper ou de déléguer à un autre objet.
Les exemples les plus typiques sont les proxys distants, les initialiseurs d'objets lourds et les proxys d'accès.
Proxy distant - le sujet se trouve sur un serveur distant, une JVM différente ou même un système non Java. Le proxy traduit les appels de méthode en appels RMI / REST / SOAP ou tout ce qui est nécessaire, protégeant le client de l'exposition à la technologie sous-jacente.
Lazy Load Proxy - initialise complètement l'objet uniquement lors de la première utilisation ou de la première utilisation intensive.
Proxy d'accès - contrôlez l'accès au sujet.
Façade
La façade est étroitement associée au principe de conception des moindres connaissances (loi de Déméter). La façade est très similaire à l'adaptateur. Ils enveloppent tous les deux, ils mappent tous les deux un objet à un autre, mais ils diffèrent dans l'intention. La façade aplatit la structure complexe d'un sujet, le graphique d'objet complexe, simplifiant l'accès à une structure complexe.
La façade enveloppe une structure complexe, lui fournissant une interface plate. Cela empêche l'objet client d'être exposé aux relations internes dans la structure du sujet, ce qui favorise le couplage lâche.
Pont
Variante plus complexe du modèle d'adaptateur où non seulement l'implémentation varie mais aussi l'abstraction. Il ajoute une indirection supplémentaire à la délégation. La délégation supplémentaire est le pont. Il dissocie l'adaptateur même de l'adaptation de l'interface. Il augmente la complexité plus que tout autre des autres modèles d'emballage, alors appliquez avec soin.
Différences de constructeurs
Les différences de modèle sont également évidentes lorsque l'on regarde leurs constructeurs.
Le proxy n'encapsule pas un objet existant. Il n'y a pas de sujet dans le constructeur.
Décorateur et adaptateur encapsule un objet déjà existant, et tel est généralement
fourni dans le constructeur.
Le constructeur de façade prend l'élément racine d'un graphique d'objet entier, sinon il ressemble à Adapter.
Exemple réel - Adaptateur de marshaling JAXB . Le but de cet adaptateur est de mapper une classe plate simple à une structure plus complexe requise en externe et d'éviter la classe de sujet "polluante" avec des annotations excessives.