En quoi les modèles de proxy, de décorateur, d'adaptateur et de pont diffèrent-ils?


403

Je regardais le modèle de proxy, et pour moi, cela ressemble énormément aux modèles de décorateur, d'adaptateur et de pont. Suis-je en train de mal comprendre quelque chose? Quelle est la différence? Pourquoi devrais-je utiliser le modèle de proxy par rapport aux autres? Comment les avez-vous utilisés dans le passé dans des projets du monde réel?


4
Il existe souvent des modèles qui se ressemblent beaucoup, mais dont l'intention diffère (la stratégie et les modèles d'état viennent à l'esprit). Je pense que cela est souvent dû au fait que les modèles de conception sont basés sur des principes de conception solides communs.
Jason Down

5
Eh bien, ces quatre modèles ont exactement les mêmes détails d'implémentation. La stratégie des versets d'État peut au moins être résumée comme des versets d'état sans état (pour la plupart). Souvent, la stratégie n'est qu'une injection de méthode, où le modèle d'état utilise une interface pour faire plus qu'abstraire un appel de méthode. La stratégie, également, au bout du compte, est un hack pour permettre une programmation fonctionnelle dans le monde OO.
Charles Graham

Réponses:


648

Le proxy, le décorateur, l'adaptateur et le pont sont tous des variantes de "l'habillage" d'une classe. Mais leurs utilisations sont différentes.

  • Le proxy peut être utilisé lorsque vous souhaitez instancier un objet paresseusement, masquer le fait que vous appelez un service distant ou contrôler l'accès à l'objet.

  • Le décorateur est également appelé «Smart Proxy». Ceci est utilisé lorsque vous souhaitez ajouter des fonctionnalités à un objet, mais pas en étendant le type de cet objet. Cela vous permet de le faire lors de l'exécution.

  • L'adaptateur est utilisé lorsque vous avez une interface abstraite et que vous souhaitez mapper cette interface à un autre objet qui a un rôle fonctionnel similaire, mais une interface différente.

  • Bridge est très similaire à Adapter, mais nous l'appelons Bridge lorsque vous définissez à la fois l'interface abstraite et l'implémentation sous-jacente. C'est-à-dire que vous ne vous adaptez pas à un code hérité ou tiers, vous êtes le concepteur de tout le code, mais vous devez pouvoir échanger différentes implémentations.

  • La façade est une interface de niveau supérieur (lire: plus simple) vers un sous-système d'une ou plusieurs classes. Supposons que vous ayez un concept complexe qui nécessite la représentation de plusieurs objets. Apporter des modifications à cet ensemble d'objets est source de confusion, car vous ne savez pas toujours quel objet possède la méthode que vous devez appeler. C'est le moment d'écrire une façade qui fournit des méthodes de haut niveau pour toutes les opérations complexes que vous pouvez effectuer pour la collection d'objets. Exemple: un modèle de domaine pour une section de l' école, avec des méthodes comme countStudents(), reportAttendance(), assignSubstituteTeacher()et ainsi de suite.


7
Bonne réponse. Peut-être vaut-il la peine d'ajouter quelques exemples où vous le voyez à l'état sauvage? par exemple, les classes de proxy dans les services Web. +1 de moi.
Rob Cooper

5
@Rob: merci, mais je préfère garder cette réponse courte et douce. Je vous encourage à écrire une autre réponse avec des exemples dans la nature!
Bill Karwin

8
@RobertDailey Decorator est également bon pour éviter les hiérarchies de type hors de contrôle. Par exemple , supposons que vous ayez une fenêtre dans une interface graphique et que vous souhaitiez avoir des barres de défilement facultatives. Vous pouvez avoir des classes Window, VScrollWindow, HScrollWindow et VHScrollWindow ou vous pouvez créer des décorateurs VScroll et HScroll sur Window.
Eva

1
@RobertDailey, Decorator est la composition.
Bill Karwin

1
Et si vous souhaitez dupliquer l'interface de l'objet encapsulé 1: 1, puis ajouter quelques méthodes supplémentaires? Est-ce un décorateur ou un adaptateur?
donquixote du

198

Comme le dit la réponse de Bill, leurs cas d'utilisation sont différents .

Leurs structures aussi.

  • Le proxy et le décorateur ont tous deux la même interface que leurs types encapsulés, mais le proxy crée une instance sous le capot, tandis que le décorateur prend une instance dans le constructeur.

  • L'adaptateur et la façade ont tous deux une interface différente de ce qu'ils enveloppent. Mais l'adaptateur dérive d'une interface existante, tandis que la façade crée une nouvelle interface.

  • Le pont et l' adaptateur pointent tous deux vers un type existant. Mais le pont pointe vers un type abstrait et l'adaptateur peut pointer vers un type concret. Le pont vous permettra de coupler l'implémentation lors de l'exécution, contrairement à l'adaptateur.


30
Votre réponse combinée avec celle de Bill résume très bien 5 chapitres de Design Patterns. On pourrait les appeler une interface de niveau supérieur (lire: plus simple) du livre.
Jonas Eicher

54

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.


30

Il y a beaucoup de chevauchements dans de nombreux modèles du GoF. Ils sont tous construits sur le pouvoir du polymorphisme et parfois ne diffèrent vraiment que dans leur intention. (stratégie vs état)

Ma compréhension des modèles a été multipliée par 100 après avoir lu les modèles de conception Head First .

Je le recommande fortement!


9

Toutes les bonnes réponses des experts ont déjà expliqué ce que représente chaque modèle.

Je décorerai les points clés.

Décorateur:

  1. Ajoutez un comportement à l'objet au moment de l'exécution . L'héritage est la clé pour atteindre cette fonctionnalité, qui est à la fois un avantage et un inconvénient de ce modèle.
  2. Il modifie le comportement de l'interface.

par exemple (avec chaînage): java.ioclasses de packages liées aux InputStream& OutputStreaminterfaces

FileOutputStream fos1 = new FileOutputStream("data1.txt");  
ObjectOutputStream out1 = new ObjectOutputStream(fos1);

Procuration:

  1. Utilisez-le pour l'initialisation paresseuse, l'amélioration des performances en mettant en cache l'objet et en contrôlant l'accès au client / appelant . Il peut fournir un comportement alternatif ou appeler un objet réel. Au cours de ce processus, il peut créer un nouvel objet.
  2. Contrairement à Decorator , qui permet le chaînage d'objets, Proxy ne permet pas le chaînage.

par exemple: java.rmiclasses de packages.

Adaptateur:

  1. Il permet à deux interfaces indépendantes de travailler ensemble à travers les différents objets , jouant éventuellement le même rôle.
  2. Il modifie l'interface d'origine .

par exemple java.io.InputStreamReader( InputStreamrenvoie a Reader)

Pont:

  1. Il permet aux abstractions et aux implémentations de varier indépendamment .
  2. Il utilise la composition plutôt que l'héritage .

par exemple des cours Collection en java.util. Listmis en œuvre par ArrayList.

Notes clés:

  1. L'adaptateur fournit une interface différente à son sujet. Le proxy fournit la même interface. Decorator fournit une interface améliorée.
  2. L'adaptateur modifie l'interface d'un objet, Decorator augmente les responsabilités d'un objet.
  3. Décorateur et Proxy ont des objectifs différents mais des structures similaires
  4. L'adaptateur fait fonctionner les choses après leur conception; Pont fait fonctionner avant qu'ils ne le soient.
  5. Bridge est conçu à l'avance pour laisser l'abstraction et la mise en œuvre varier indépendamment. Adaptateur est mis à niveau pour que les classes non liées fonctionnent ensemble
  6. Décorateur est conçu pour vous permettre d'ajouter des responsabilités aux objets sans sous-classement.

Jetez un oeil à de grandes questions / articles SE concernant des exemples de différents modèles de conception

Quand utiliser le motif décorateur?

Quand utilisez-vous le Bridge Pattern? En quoi est-il différent du modèle d'adaptateur?

Différences entre le proxy et le modèle de décorateur


8

Ils sont assez similaires et les lignes entre eux sont assez grises. Je vous suggère de lire les entrées Proxy Pattern et Decorator Pattern dans le wiki c2.

Les entrées et les discussions y sont assez nombreuses, et elles renvoient également à d'autres articles pertinents. Soit dit en passant, le wiki c2 est excellent lorsque l'on s'interroge sur les nuances entre les différents modèles.

Pour résumer les entrées c2, je dirais qu'un décorateur ajoute / modifie le comportement, mais un proxy a plus à voir avec le contrôle d'accès (instanciation paresseuse, accès à distance, sécurité, etc.). Mais comme je l'ai dit, les lignes entre eux sont grises et je vois des références à des mandataires qui pourraient facilement être considérés comme des décorateurs et vice versa.


4

Tous les quatre modèles impliquent d'envelopper un objet / classe interne avec un objet externe, ils sont donc très similaires structurellement. Je soulignerais la différence par le but:

  • Le proxy encapsule l'accès de l'extérieur vers l'intérieur.
  • Décorateur modifie ou étend le comportement de l'intérieur avec l'extérieur.
  • L'adaptateur convertit l'interface de l'intérieur vers l'extérieur.
  • Le pont sépare la partie invariable du comportement (externe) de la partie variable ou dépendante de la plateforme (interne).

Et par variation d'interface entre les objets internes et externes:

  • dans les interfaces proxy sont les mêmes.
  • dans les interfaces Decorator sont les mêmes.
  • dans les interfaces d' adaptateur sont formellement différentes, mais remplissent le même objectif.
  • dans Bridge, les interfaces sont conceptuellement différentes.

4

Ceci est une citation de Head First Design Patterns

Les définitions appartiennent au livre. Les exemples m'appartiennent.

Décorateur - Ne modifie pas l'interface, mais ajoute des responsabilités. Supposons que vous ayez une interface de voiture, lorsque vous l'implémentez pour différents modèles de voiture (s, sv, sl), vous devrez peut-être ajouter plus de responsabilité pour certains modèles. Comme le toit ouvrant, l'airbag, etc.

Adaptateur - Convertit une interface en une autre. Vous avez une interface de voiture et vous aimeriez qu'elle agisse comme une jeep. Vous prenez donc la voiture, la modifiez et vous vous transformez en jeep. Comme ce n'est pas une vraie jeep. Mais agit comme une jeep.

Façade - Rend une interface plus simple. Supposons que vous ayez des interfaces voiture, avion, navire. En fait, tout ce dont vous avez besoin est une classe qui envoie des gens d'un endroit à un autre. Vous voulez que la façade décide du véhicule à utiliser. Ensuite, vous rassemblez toutes ces références d'interface sous 1 parapluie et laissez-le décider / déléguer pour rester simple.

Head First: "Une façade simplifie non seulement une interface, elle dissocie un client d'un sous-système de composants. Les façades et les adaptateurs peuvent encapsuler plusieurs classes, mais l'intention d'une façade est de simplifier, tandis qu'un adaptateur consiste à convertir l'interface en quelque chose de différent. "


1

Je l'utilise assez souvent lors de la consommation de services Web. Le modèle de proxy devrait probablement être renommé en quelque chose de plus pragmatique, comme «Wrapper Pattern". J'ai également une bibliothèque qui est un proxy pour MS Excel. Cela facilite l'automatisation d'Excel, sans avoir à se soucier des détails d'arrière-plan tels que la version est installée (le cas échéant).


Ne serait-ce pas simplement le modèle d'adaptateur?
Charles Graham

1
Un service Web est consommé par un proxy, tandis que le modèle d'adaptateur est davantage utilisé pour la conversion ou la traduction de données d'un formulaire à un autre.
hmcclungiii

1

En parlant d'implémentation détaillée, je trouve une différence entre Proxy et Decorator, Adapter, Facade ... Dans l'implémentation courante de ces modèles, il y a un objet cible enveloppé par un objet englobant. Le client utilise un objet englobant au lieu de l'objet cible. Et l'objet cible joue en fait un rôle important à l'intérieur de certaines méthodes de confinement de l'objet.

Cependant, dans le cas du proxy, un objet englobant peut jouer certaines méthodes par lui-même, il initialise simplement l'objet cible lorsque le client appelle certaines méthodes dont il a besoin que l'objet cible participe. Il s'agit d'une initialisation paresseuse. Dans le cas d'autres modèles, entourer l'objet est virtuellement basé sur l'objet cible. Ainsi, l'objet cible est toujours initialisé avec l'objet englobant dans les constructeurs / setters.

Une autre chose, un proxy fait exactement ce que fait une cible tandis que d'autres modèles ajoutent plus de fonctionnalités à la cible.


1

Je voudrais ajouter des exemples à la réponse de Bill Karwing (ce qui est très bien.) J'ajoute également quelques différences clés de mise en œuvre qui, selon moi, manquent

Les parties citées proviennent de la réponse de [ https://stackoverflow.com/a/350471/1984346] (Bill Karwing)

Le proxy, le décorateur, l'adaptateur et le pont sont tous des variantes de "l'habillage" d'une classe. Mais leurs utilisations sont différentes.

  • Le proxy peut être utilisé lorsque vous souhaitez instancier un objet paresseusement, masquer le fait que vous appelez un service distant ou contrôler l'accès à l'objet.

ProxyClass et ObjectClass qui sont mandatés, doivent implémenter la même interface, afin qu'ils soient interchangeables

Exemple - objet cher proxy

class ProxyHumanGenome implements GenomeInterface  {
    private $humanGenome = NULL; 

    // humanGenome class is not instantiated at construct time
    function __construct() {
    }

    function getGenomeCount() {
        if (NULL == $this->humanGenome) {
            $this->instantiateGenomeClass(); 
        }
        return $this->humanGenome->getGenomeCount();
    }
} 
class HumanGenome implement GenomeInterface { ... }
  • Le décorateur est également appelé «Smart Proxy». Ceci est utilisé lorsque vous souhaitez ajouter des fonctionnalités à un objet, mais pas en étendant le type de cet objet. Cela vous permet de le faire lors de l'exécution.

DecoratorClass devrait (pourrait) implémenter une interface étendue d'ObjectClass. Ainsi, l'ObjectClass pourrait être remplacé par DecoratorClass, mais pas l'inverse.

Exemple - ajout de fonctionnalités supplémentaires

class DecoratorHumanGenome implements CheckGenomeInterface  {

    // ... same code as previous example

    // added functionality
    public function isComplete() {
        $this->humanGenome->getCount >= 21000
    }
}

interface CheckGenomeInterface extends GenomeInterface {

    public function isComplete();

}

class HumanGenome implement GenomeInterface { ... }
  • L'adaptateur est utilisé lorsque vous avez une interface abstraite et que vous souhaitez mapper cette interface à un autre objet qui a un rôle fonctionnel similaire, mais une interface différente.

Différences d'implantation Proxy, Decorator, Adapter

L'adaptateur fournit une interface différente à son sujet. Le proxy fournit la même interface. Decorator fournit une interface améliorée.

  • Bridge est très similaire à Adapter, mais nous l'appelons Bridge lorsque vous définissez à la fois l'interface abstraite et l'implémentation sous-jacente. C'est-à-dire que vous ne vous adaptez pas à un code hérité ou tiers, vous êtes le concepteur de tout le code, mais vous devez pouvoir échanger différentes implémentations.

  • La façade est une interface de niveau supérieur (lire: plus simple) vers un sous-système d'une ou plusieurs classes. Supposons que vous ayez un concept complexe qui nécessite la représentation de plusieurs objets. Apporter des modifications à cet ensemble d'objets est source de confusion, car vous ne savez pas toujours quel objet possède la méthode que vous devez appeler. C'est le moment d'écrire une façade qui fournit des méthodes de haut niveau pour toutes les opérations complexes que vous pouvez effectuer pour la collection d'objets. Exemple: un modèle de domaine pour une section de l' école, avec des méthodes comme countStudents(), reportAttendance(), assignSubstituteTeacher()et ainsi de suite.

La plupart des informations dans cette réponse proviennent de https://sourcemaking.com/design_patterns , que je recommande comme une excellente ressource pour les modèles de conception.


0

Je crois que le code donnera des idées claires (pour compléter les autres réponses également). Veuillez voir ci-dessous, (Concentrez-vous sur les types qu'une classe implémente et encapsule)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            /* Proxy */

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("PROXY");
            Console.WriteLine(Environment.NewLine);

            //instead of creating here create using a factory method, the facory method will return the proxy
            IReal realProxy = new RealProxy();
            Console.WriteLine("calling do work with the proxy object ");
            realProxy.DoWork();

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("ADAPTER");
            Console.WriteLine(Environment.NewLine);

            /*Adapter*/
            IInHand objectIHave = new InHand();
            Api myApi = new Api();
            //myApi.SomeApi(objectIHave); /*I cant do this, use a adapter then */
            IActual myAdaptedObject = new ActualAdapterForInHand(objectIHave);
            Console.WriteLine("calling api with  my adapted obj");
            myApi.SomeApi(myAdaptedObject);


            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("DECORATOR");
            Console.WriteLine(Environment.NewLine);

            /*Decorator*/
            IReady maleReady = new Male();
            Console.WriteLine("now male is going to get ready himself");
            maleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReady = new Female();
            Console.WriteLine("now female is going to get ready her self");
            femaleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady maleReadyByBeautician = new Beautician(maleReady);
            Console.WriteLine("now male is going to get ready by beautician");
            maleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReadyByBeautician = new Beautician(femaleReady);
            Console.WriteLine("now female is going to get ready by beautician");
            femaleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            Console.ReadLine();


        }
    }

    /*Proxy*/

    public interface IReal
    {
        void DoWork();
    }

    public class Real : IReal
    {
        public void DoWork()
        {
            Console.WriteLine("real is doing work ");
        }
    }


    public class RealProxy : IReal
    {
        IReal real = new Real();

        public void DoWork()
        {
            real.DoWork();
        }
    }

    /*Adapter*/

    public interface IActual
    {
        void DoWork();
    }

    public class Api
    {
        public void SomeApi(IActual actual)
        {
            actual.DoWork();
        }
    }

    public interface IInHand
    {
        void DoWorkDifferently();
    }

    public class InHand : IInHand
    {
        public void DoWorkDifferently()
        {
            Console.WriteLine("doing work slightly different ");
        }
    }

    public class ActualAdapterForInHand : IActual
    {
        IInHand hand = null;

        public ActualAdapterForInHand()
        {
            hand = new InHand();
        }

        public ActualAdapterForInHand(IInHand hnd)
        {
            hand = hnd;
        }

        public void DoWork()
        {
            hand.DoWorkDifferently();
        }
    }

    /*Decorator*/

    public interface IReady
    {
        void GetReady();
    }

    public class Male : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
        }
    }

    public class Female : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
            Console.WriteLine("Make up....");
        }
    }

    //this is a decorator
    public class Beautician : IReady
    {
        IReady ready = null;

        public Beautician(IReady rdy)
        {
            ready = rdy;
        }

        public void GetReady()
        {
            ready.GetReady();
            Console.WriteLine("Style hair ");

            if (ready is Female)
            {
                for (int i = 1; i <= 10; i++)
                {
                    Console.WriteLine("doing ready process " + i);
                }

            }
        }
    }

}

-3

Le modèle de conception n'est pas des mathématiques, c'est une combinaison d'art et de génie logiciel. Il n'y a rien de tel pour cette exigence que vous devez utiliser un proxy, un pont, etc. Des modèles de conception sont créés pour résoudre les problèmes. Si vous prévoyez un problème de conception, utilisez-le. Sur la base de l'expérience, vous découvrirez, pour un problème spécifique, quel modèle utiliser. Si vous êtes bon dans les principes de conception solides, vous auriez implémenté un modèle de conception sans savoir qu'il s'agit d'un modèle. Un exemple courant est les modèles de statergy et d'usine

Par conséquent, concentrez-vous davantage sur les principes de conception solides, les principes de codage propre et le ttd


D'accord, mais cela ne répond pas à la question.
Leon
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.