In che modo differiscono i modelli proxy, decoratore, adattatore e bridge?


403

Stavo guardando il modello del proxy, e per me sembra molto simile ai motivi del decoratore, dell'adattatore e del ponte. Sto fraintendendo qualcosa? Qual è la differenza? Perché dovrei usare il modello Proxy rispetto agli altri? Come li hai usati in passato nei progetti del mondo reale?


4
Ci sono spesso modelli che sembrano molto simili, ma differiscono nelle loro intenzioni (vengono in mente i modelli di strategia e di stato). Penso che ciò sia spesso dovuto al fatto che i modelli di progettazione si basano su solidi principi di progettazione comuni.
Jason Down,

5
Bene, questi quattro schemi hanno gli stessi dettagli di implementazione. La strategia dei versi di stato può almeno essere riassunta in versi statali e pieni di stato (per la maggior parte). Spesso, la strategia è solo l'iniezione di metodo, in cui il modello di stato utilizza un'interfaccia per fare di più quindi astrarre una chiamata di metodo. La strategia, inoltre, alla fine della giornata, è un hack per consentire la programmazione funzionale nel mondo OO.
Charles Graham,

Risposte:


648

Proxy, Decorator, Adapter e Bridge sono tutte varianti di "wrapping" di una classe. Ma i loro usi sono diversi.

  • Il proxy può essere utilizzato quando si desidera creare un'istanza pigra di un oggetto o nascondere il fatto che si sta chiamando un servizio remoto o controllare l'accesso all'oggetto.

  • Decorator è anche chiamato "Smart Proxy". Viene utilizzato quando si desidera aggiungere funzionalità a un oggetto, ma non estendendo il tipo di oggetto. Ciò ti consente di farlo in fase di esecuzione.

  • L'adattatore viene utilizzato quando si dispone di un'interfaccia astratta e si desidera mappare tale interfaccia su un altro oggetto che ha un ruolo funzionale simile, ma un'interfaccia diversa.

  • Bridge è molto simile a Adapter, ma lo chiamiamo Bridge quando definisci sia l'interfaccia astratta che l'implementazione sottostante. Vale a dire che non ti stai adattando ad alcuni codici legacy o di terze parti, sei il progettista di tutto il codice ma devi essere in grado di scambiare diverse implementazioni.

  • Facade è un'interfaccia di livello superiore (leggi: più semplice) per un sottosistema di una o più classi. Supponiamo di avere un concetto complesso che richiede la rappresentazione di più oggetti. Apportare modifiche a quel set di oggetti è confuso, perché non si sa sempre quale oggetto ha il metodo da chiamare. Questo è il momento di scrivere una facciata che fornisce metodi di alto livello per tutte le complesse operazioni che è possibile eseguire per la raccolta di oggetti. Esempio: un modello di dominio per una sezione di scuola, con metodi come countStudents(), reportAttendance(), assignSubstituteTeacher()e così via.


7
Buona risposta. Potrebbe valere la pena aggiungere alcuni esempi di dove lo vedi in natura? ad es. classi proxy in servizi Web. +1 da me.
Rob Cooper,

5
@Rob: grazie, ma preferirei che questa risposta fosse breve e dolce. Ti incoraggio a scrivere un'altra risposta con esempi in libertà!
Bill Karwin,

8
@RobertDailey Decorator è anche utile per evitare gerarchie di tipi fuori controllo. Ad esempio , supponiamo che tu abbia una finestra in una GUI e desideri avere barre di scorrimento opzionali. Potresti avere le classi Window, VScrollWindow, HScrollWindow e VHScrollWindow oppure puoi creare i decoratori VScroll e HScroll su Window.
Eva,

1
@RobertDailey, Decorator è composizione.
Bill Karwin,

1
E se si desidera duplicare l'interfaccia dell'oggetto avvolto 1: 1 ma quindi aggiungere alcuni metodi aggiuntivi? È un decoratore o un adattatore?
donquixote,

198

Come dice la risposta di Bill, i loro casi d'uso sono diversi .

Così sono le loro strutture.

  • Proxy e Decorator hanno entrambi la stessa interfaccia dei loro tipi di wrapping, ma il proxy crea un'istanza sotto il cofano, mentre il decoratore prende un'istanza nel costruttore.

  • Adapter e Facade hanno entrambi un'interfaccia diversa da quella che avvolgono. Ma l'adattatore deriva da un'interfaccia esistente, mentre la facciata crea una nuova interfaccia.

  • Bridge e Adapter indicano entrambi un tipo esistente. Ma il bridge punterà a un tipo astratto e l'adattatore potrebbe puntare a un tipo concreto. Il bridge ti consentirà di accoppiare l'implementazione in fase di esecuzione, mentre l'adattatore di solito non lo farà.


30
La tua risposta combinata con Bill avvolge 5 capitoli di Design Patterns molto bene. Si potrebbe chiamarli un'interfaccia di livello superiore (leggi: più semplice) per il libro.
Jonas Eicher,

54

La mia opinione sull'argomento.

Tutti e quattro i motivi hanno molto in comune, tutti e quattro sono talvolta chiamati in modo informale wrapper o modelli di wrapper. Tutti usano la composizione, avvolgendo il soggetto e delegando l'esecuzione al soggetto ad un certo punto, mappando una chiamata di metodo a un'altra. Risparmiano al cliente la necessità di dover costruire un oggetto diverso e copiarlo su tutti i dati rilevanti. Se usati con saggezza, risparmiano memoria e processore.

Promuovendo l'accoppiamento libero rendono il codice una volta stabile meno esposto alle inevitabili modifiche e meglio leggibile per gli altri sviluppatori.

Adattatore

L'adattatore adatta il soggetto (adattato) a un'interfaccia diversa. In questo modo possiamo aggiungere l'oggetto da collocare in una raccolta di tipi nominalmente diversi.

L'adapter espone al client solo metodi pertinenti, può limitare tutti gli altri, rivelando gli intenti di utilizzo per contesti particolari, come ad esempio l'adattamento della libreria esterna, rendendolo meno generale e più focalizzato sulle esigenze della nostra applicazione. Gli adattatori aumentano la leggibilità e l'auto-descrizione del nostro codice.

Gli adattatori proteggono una squadra dal codice volatile di altre squadre; uno strumento salvavita quando si tratta di squadre offshore ;-)

Lo scopo meno menzionato è quello di impedire alla classe soggetto di eccedere le annotazioni. Con così tanti framework basati su annotazioni, questo diventa un utilizzo più importante che mai.

L'adapter consente di aggirare la limitazione Java della sola eredità. Può combinare più adattati in un'unica busta dando l'impressione di ereditarietà multipla.

Per quanto riguarda il codice, l'adattatore è "sottile". Non dovrebbe aggiungere molto codice alla classe degli adattati, oltre a chiamare semplicemente il metodo degli adattati e occasionali conversioni di dati necessarie per effettuare tali chiamate.

Non ci sono molti buoni esempi di adattatori in JDK o nelle librerie di base. Gli sviluppatori di applicazioni creano adattatori, per adattare le librerie alle interfacce specifiche dell'applicazione.

Decoratore

Decorator non solo delega, non solo mappa un metodo su un altro, fa di più, modifica il comportamento di alcuni metodi del soggetto, può decidere di non chiamare affatto il metodo del soggetto, delegare a un altro oggetto, un oggetto helper.

I decoratori in genere aggiungono funzionalità (in modo trasparente) all'oggetto avvolto come registrazione, crittografia, formattazione o compressione sull'oggetto. Questa nuova funzionalità può portare molto nuovo codice. Quindi, i decoratori di solito sono molto più "grassi" degli adattatori.

Il decoratore deve essere una sottoclasse dell'interfaccia del soggetto. Possono essere usati in modo trasparente invece dei suoi soggetti. Vedi BufferedOutputStream, è ancora OutputStream e può essere usato come tale. Questa è una grande differenza tecnica rispetto agli adattatori.

Esempi di libri di testo dell'intera famiglia di decoratori si trovano facilmente in JDK - Java IO. Tutte le classi come BufferedOutputStream , FilterOutputStream e ObjectOutputStream sono decoratori di OutputStream . Possono essere a strati di cipolla, dove un solo decoratore viene nuovamente decorato, aggiungendo più funzionalità.

delega

Il proxy non è un wrapper tipico. L'oggetto spostato, l'oggetto del proxy, potrebbe non esistere al momento della creazione del proxy. Il proxy spesso lo crea internamente. Può essere un oggetto pesante creato su richiesta, oppure è un oggetto remoto in JVM diverso o nodo di rete diverso e persino un oggetto non Java, un componente nel codice nativo. Non deve affatto avvolgere o delegare a un altro oggetto.

Gli esempi più tipici sono proxy remoti, inizializzatori di oggetti pesanti e proxy di accesso.

  • Proxy remoto: l'oggetto si trova su un server remoto, su un altro JVM o anche su un sistema non Java. Il proxy traduce le chiamate di metodo a chiamate RMI / REST / SOAP o qualsiasi altra cosa sia necessaria, proteggendo il cliente dall'esposizione alla tecnologia sottostante.

  • Proxy di caricamento lento: inizializza completamente l'oggetto solo al primo utilizzo o al primo utilizzo intensivo.

  • Proxy d'accesso: controlla l'accesso al soggetto.

Facciata

La facciata è strettamente associata al principio di progettazione della conoscenza minima (Legge di Demetra). La facciata è molto simile all'adattatore. Si avvolgono entrambi, entrambi mappano un oggetto su un altro, ma differiscono nell'intento. La facciata appiattisce la struttura complessa di un soggetto, il grafico di un oggetto complesso, semplificando l'accesso a una struttura complessa.

La facciata avvolge una struttura complessa, fornendo un'interfaccia piatta ad essa. Ciò impedisce che l'oggetto client venga esposto alle relazioni interne nella struttura del soggetto, promuovendo quindi l'accoppiamento libero.

ponte

Variante più complessa del modello di adattatore in cui non solo l'implementazione varia ma anche l'astrazione. Aggiunge un'altra indiretta alla delegazione. La delegazione extra è il ponte. Disaccoppia l'adattatore anche dall'interfaccia adattante. Aumenta la complessità più di ogni altro modello di avvolgimento, quindi applica con cura.

Differenze nei costruttori

Le differenze di modello sono evidenti anche quando si osservano i loro costruttori.

  • Il proxy non sta avvolgendo un oggetto esistente. Non c'è argomento nel costruttore.

  • Decoratore e Adattatore avvolgono oggetti già esistenti, e questo è in genere
    fornito nel costruttore.

  • Il costruttore di facciate prende l'elemento radice di un intero oggetto grafico, altrimenti sembra uguale all'adapter.

Esempio di vita reale - Marshalling Adapter JAXB . Lo scopo di questo adattatore è la mappatura di una semplice classe piatta su una struttura più complessa richiesta esternamente e per prevenire la classe soggetto "inquinante" con annotazioni eccessive.


30

C'è molta sovrapposizione in molti dei modelli GoF. Sono tutti costruiti sul potere del polimorfismo e talvolta differiscono solo per l'intento. (strategia vs. stato)

La mia comprensione dei modelli è cresciuta di 100 volte dopo aver letto i primi modelli di progettazione .

Lo consiglio vivamente!


9

Tutte le buone risposte degli esperti hanno già spiegato cosa significa ogni modello.

Io decorare i punti chiave.

Decoratore:

  1. Aggiungi comportamento all'oggetto in fase di esecuzione . L'ereditarietà è la chiave per ottenere questa funzionalità, che è sia un vantaggio che uno svantaggio di questo modello.
  2. Modifica il comportamento dell'interfaccia.

ad es. (con concatenamento): java.ioclassi di pacchetti relative a InputStream& OutputStreaminterfacce

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

Proxy:

  1. Usalo per l'inizializzazione lenta, il miglioramento delle prestazioni memorizzando nella cache l'oggetto e controllando l'accesso al client / chiamante . Può fornire un comportamento alternativo o chiamare un oggetto reale. Durante questo processo, può creare un nuovo oggetto.
  2. A differenza di Decorator , che consente il concatenamento di oggetti, Proxy non consente il concatenamento.

ad es .: java.rmiclassi di pacchetti.

Adattatore:

  1. Permette a due interfacce non correlate di lavorare insieme attraverso i diversi oggetti , possibilmente giocando lo stesso ruolo.
  2. Modifica l'interfaccia originale .

ad es. java.io.InputStreamReader( InputStreamrestituisce a Reader)

Ponte:

  1. Permette alle astrazioni e alle implementazioni di variare indipendentemente .
  2. Usa la composizione sull'eredità .

es. lezioni di raccolta in java.util. Listimplementato da ArrayList.

Note chiave:

  1. L'adattatore fornisce un'interfaccia diversa rispetto al soggetto. Il proxy fornisce la stessa interfaccia. Decorator offre un'interfaccia migliorata.
  2. L'adattatore cambia l'interfaccia di un oggetto, Decorator migliora le responsabilità di un oggetto.
  3. Decoratore e Proxy hanno scopi diversi ma strutture simili
  4. L'adattatore fa funzionare le cose dopo che sono state progettate; Bridge li fa funzionare prima che lo siano.
  5. Bridge è progettato in anticipo per consentire all'astrazione e all'implementazione di variare in modo indipendente. L'adattatore è adattato per far lavorare insieme le classi non correlate
  6. Decorator è progettato per consentire di aggiungere responsabilità agli oggetti senza sottoclasse.

Dai un'occhiata alle grandi domande / articoli SE riguardanti esempi di vari modelli di design

Quando utilizzare il motivo decorativo?

Quando usi il modello Bridge? In cosa differisce dal modello di adattatore?

Differenze tra proxy e motivo decorativo


8

Sono abbastanza simili e le linee tra loro sono piuttosto grigie. Ti suggerisco di leggere il voci Proxy Pattern e Decorator Pattern nel wiki c2.

Le voci e le discussioni sono piuttosto estese e si collegano anche ad altri articoli pertinenti. A proposito, il wiki c2 è eccellente quando ci si chiede quali siano le sfumature tra i diversi schemi.

Per riassumere le voci di c2, direi che un decoratore aggiunge / modifica il comportamento, ma un proxy ha più a che fare con il controllo degli accessi (istanza pigra, accesso remoto, sicurezza ecc.). Ma come ho detto, le linee tra loro sono grigie e vedo riferimenti a proxy che potrebbero essere facilmente visualizzati come decoratori e viceversa.


4

Tutti e quattro i modelli implicano un avvolgimento di oggetto / classe interni con uno esterno, quindi strutturalmente sono molto simili. Vorrei delineare la differenza in base allo scopo:

  • Il proxy incapsula l'accesso dall'esterno all'interno.
  • Decoratore modifica o estende il comportamento di interno con esterno.
  • L'adattatore converte l'interfaccia dall'interno all'esterno.
  • Bridge separa la parte invariabile del comportamento (esterna) dalla parte variabile o dipendente dalla piattaforma (interna).

E dalla variazione dell'interfaccia tra oggetti interni ed esterni:

  • nelle interfacce proxy sono le stesse.
  • nelle interfacce di Decorator sono le stesse.
  • nelle interfacce dell'adattatore sono diverse formalmente, ma soddisfano lo stesso scopo.
  • in Bridge le interfacce sono concettualmente diverse.

4

Questa è la citazione da Head First Design Patterns

Le definizioni appartengono al libro. Gli esempi mi appartengono.

Decoratore : non altera l'interfaccia, ma aggiunge responsabilità. Supponiamo di avere un'interfaccia per auto, quando la implementate per diversi modelli di auto (s, sv, sl) potrebbe essere necessario aggiungere più responsabilità per alcuni modelli. Come ha tetto apribile, airbag ecc.

Adattatore : converte un'interfaccia in un'altra. Hai un'interfaccia per auto e vorresti che si comportasse come una jeep. Quindi prendi la macchina, la modifichi e la trasformi in una jeep. Dal momento che non è una vera jeep. Ma si comporta come una jeep.

Facciata : semplifica l'interfaccia. Supponiamo di avere interfacce auto, aereo, nave. In realtà tutto ciò che serve è una classe che manda le persone da una posizione all'altra. Vuoi che la facciata decida quale veicolo usare. Quindi raccogli tutti quei riferimenti all'interfaccia sotto 1 ombrello e lascia che decida / delegare per mantenerlo semplice.

Prima di tutto: "Una facciata non solo semplifica un'interfaccia, ma separa un client da un sottosistema di componenti. Le facciate e gli adattatori possono avvolgere più classi, ma l'intento di una facciata è semplificare, mentre un adattatore deve convertire l'interfaccia in qualcosa di diverso. "


1

Lo uso abbastanza spesso quando utilizzo i servizi Web. Probabilmente il Proxy Pattern dovrebbe essere rinominato in qualcosa di più pragmatico, come "Wrapper Pattern". Ho anche una libreria che è un proxy per MS Excel. Rende molto semplice automatizzare Excel, senza doversi preoccupare di dettagli come versione installata (se presente).


Non sarebbe solo il modello dell'adattatore?
Charles Graham,

1
Un servizio Web viene utilizzato da un proxy, mentre l'adattatore Pattern viene utilizzato maggiormente per la conversione o la traduzione di dati da un modulo a un altro.
hmcclungiii,

1

Parlando dell'implementazione dei dettagli, trovo una differenza tra Proxy e Decorator, Adapter, Facade ... Nell'implementazione comune di questi pattern c'è un oggetto target avvolto da un oggetto che lo racchiude. Il client utilizza l'oggetto che racchiude anziché l'oggetto di destinazione. E l'oggetto target svolge effettivamente un ruolo importante all'interno di alcuni dei metodi per racchiudere l'oggetto.

Tuttavia, nel caso di Proxy, racchiudere l'oggetto può riprodurre alcuni metodi da solo, inizializza l'oggetto target quando il client chiama alcuni metodi a cui è necessario prendere parte l'oggetto target. Questa è l'inizializzazione lazy. Nel caso di altri motivi, racchiudere l'oggetto è praticamente basato sull'oggetto target. Quindi l'oggetto target viene sempre inizializzato insieme all'oggetto racchiuso in costruttori / setter.

Un'altra cosa, un proxy fa esattamente quello che fa un bersaglio mentre altri schemi aggiungono più funzionalità al bersaglio.


1

Vorrei aggiungere esempi alla risposta di Bill Karwing (che è eccezionale tra l'altro.) Aggiungo anche alcune differenze chiave di implementazione, che ritengo mancanti

Le parti citate provengono dalla risposta di [ https://stackoverflow.com/a/350471/1984346] (Bill Karwing)

Proxy, Decorator, Adapter e Bridge sono tutte varianti di "wrapping" di una classe. Ma i loro usi sono diversi.

  • Il proxy può essere utilizzato quando si desidera creare un'istanza pigra di un oggetto o nascondere il fatto che si sta chiamando un servizio remoto o controllare l'accesso all'oggetto.

ProxyClass e ObjectClass in proxy, devono implementare la stessa interfaccia, quindi sono intercambiabili

Esempio: oggetto costoso 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 { ... }
  • Decorator è anche chiamato "Smart Proxy". Viene utilizzato quando si desidera aggiungere funzionalità a un oggetto, ma non estendendo il tipo di oggetto. Ciò ti consente di farlo in fase di esecuzione.

DecoratorClass dovrebbe (potrebbe) implementare l'interfaccia estesa di ObjectClass. Quindi ObjectClass potrebbe essere sostituito da DecoratorClass, ma non viceversa.

Esempio: aggiunta della funzionalità di aggiunta

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'adattatore viene utilizzato quando si dispone di un'interfaccia astratta e si desidera mappare tale interfaccia su un altro oggetto che ha un ruolo funzionale simile, ma un'interfaccia diversa.

Differenze di implosione Proxy, Decorator, Adapter

L'adattatore fornisce un'interfaccia diversa rispetto al soggetto. Il proxy fornisce la stessa interfaccia. Decorator offre un'interfaccia migliorata.

  • Bridge è molto simile a Adapter, ma lo chiamiamo Bridge quando definisci sia l'interfaccia astratta che l'implementazione sottostante. Vale a dire che non ti stai adattando ad alcuni codici legacy o di terze parti, sei il progettista di tutto il codice ma devi essere in grado di scambiare diverse implementazioni.

  • Facade è un'interfaccia di livello superiore (leggi: più semplice) per un sottosistema di una o più classi. Supponiamo di avere un concetto complesso che richiede la rappresentazione di più oggetti. Apportare modifiche a quel set di oggetti è confuso, perché non si sa sempre quale oggetto ha il metodo che è necessario chiamare. Questo è il momento di scrivere una facciata che fornisce metodi di alto livello per tutte le complesse operazioni che è possibile eseguire per la raccolta di oggetti. Esempio: un modello di dominio per una sezione di scuola, con metodi come countStudents(), reportAttendance(), assignSubstituteTeacher()e così via.

La maggior parte delle informazioni contenute in questa risposta proviene da https://sourcemaking.com/design_patterns , che consiglio come eccellente risorsa per i modelli di progettazione.


0

Credo che il codice fornirà idee chiare (per integrare anche le risposte degli altri). Di seguito, vedi (Concentrati sui tipi implementati e inclusi in una classe)

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

Il modello di progettazione non è matematica, è una combinazione di arte e ingegneria del software. Non c'è niente di simile per questo requisito che è necessario utilizzare proxy, bridge, ecc. Vengono creati modelli di progettazione per risolvere i problemi. Se prevedi un problema di progettazione, utilizzalo. In base all'esperienza, imparerai a conoscere il problema specifico, quale modello utilizzare. Se sei bravo nei solidi principi di progettazione, avresti implementato il modello di progettazione senza sapere che è modello. Esempio comune è la statergia e i modelli di fabbrica

Quindi concentrarsi maggiormente su solidi principi desighn, principi di codifica puliti e ttd


D'accordo, anche se non risponde alla domanda.
Leon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.