Wie unterscheiden sich die Proxy-, Decorator-, Adapter- und Bridge-Muster?


403

Ich habe mir das Proxy-Muster angesehen, und für mich scheint es den Mustern Decorator, Adapter und Bridge sehr ähnlich zu sein. Verstehe ich etwas falsch? Was ist der Unterschied? Warum sollte ich das Proxy-Muster im Vergleich zu den anderen verwenden? Wie haben Sie sie in der Vergangenheit in realen Projekten eingesetzt?


4
Es gibt oft Muster, die sehr ähnlich aussehen, sich aber in ihrer Absicht unterscheiden (die Strategie und die Zustandsmuster kommen in den Sinn). Ich denke, dies liegt oft an der Tatsache, dass Designmuster auf gemeinsamen soliden Designprinzipien basieren.
Jason Down

5
Nun, diese vier Muster haben genau die gleichen Implementierungsdetails. Zustandsverse Strategie kann zumindest als zustandslose Verse (größtenteils) ohne Staaten zusammengefasst werden. Oft ist die Strategie nur eine Methodeninjektion, bei der das Statusmuster eine Schnittstelle verwendet, um mehr zu tun, als einen Methodenaufruf zu abstrahieren. Letztendlich ist die Strategie auch ein Hack, um funktionale Programmierung in der OO-Welt zu ermöglichen.
Charles Graham

Antworten:


648

Proxy, Decorator, Adapter und Bridge sind Variationen beim "Umschließen" einer Klasse. Ihre Verwendung ist jedoch unterschiedlich.

  • Proxy kann verwendet werden, wenn Sie ein Objekt verzögert instanziieren oder die Tatsache verbergen möchten, dass Sie einen Remotedienst aufrufen, oder den Zugriff auf das Objekt steuern möchten.

  • Decorator wird auch als "Smart Proxy" bezeichnet. Dies wird verwendet, wenn Sie einem Objekt Funktionen hinzufügen möchten, jedoch nicht, indem Sie den Typ dieses Objekts erweitern. Dies ermöglicht Ihnen dies zur Laufzeit.

  • Der Adapter wird verwendet, wenn Sie eine abstrakte Schnittstelle haben und diese Schnittstelle einem anderen Objekt zuordnen möchten, das eine ähnliche funktionale Rolle, aber eine andere Schnittstelle hat.

  • Bridge ist Adapter sehr ähnlich, aber wir nennen es Bridge, wenn Sie sowohl die abstrakte Schnittstelle als auch die zugrunde liegende Implementierung definieren. Das heißt, Sie passen sich nicht an Legacy- oder Code von Drittanbietern an, Sie sind der Designer des gesamten Codes, aber Sie müssen in der Lage sein, verschiedene Implementierungen auszutauschen.

  • Facade ist eine übergeordnete (sprich: einfachere) Schnittstelle zu einem Subsystem einer oder mehrerer Klassen. Angenommen, Sie haben ein komplexes Konzept, für dessen Darstellung mehrere Objekte erforderlich sind. Das Vornehmen von Änderungen an dieser Gruppe von Objekten ist verwirrend, da Sie nicht immer wissen, welches Objekt die Methode hat, die Sie aufrufen müssen. Dies ist die Zeit, um eine Fassade zu schreiben, die allgemeine Methoden für alle komplexen Vorgänge bietet, die Sie für die Sammlung von Objekten ausführen können. Beispiel: Ein Domain Model für eine Schule Abschnitt, mit Methoden wie countStudents(), reportAttendance(), assignSubstituteTeacher(), und so weiter.


7
Gute Antwort. Vielleicht lohnt es sich, einige Beispiele dafür hinzuzufügen, wo Sie es in freier Wildbahn sehen? zB Proxy-Klassen in Web Services. +1 von mir.
Rob Cooper

5
@Rob: danke, aber ich möchte diese Antwort lieber kurz und bündig halten. Ich ermutige Sie, eine weitere Antwort mit Beispielen in freier Wildbahn zu schreiben!
Bill Karwin

8
@RobertDailey Decorator ist auch gut, um unkontrollierte Hierarchien zu vermeiden. Angenommen , Sie haben ein Fenster in einer GUI und möchten optionale Bildlaufleisten. Sie können Window-, VScrollWindow-, HScrollWindow- und VHScrollWindow-Klassen haben oder VScroll- und HScroll-Dekoratoren für Window erstellen.
Eva

1
@ RobertDailey, Dekorateur ist Komposition.
Bill Karwin

1
Und was ist, wenn Sie die Schnittstelle des umschlossenen Objekts 1: 1 duplizieren und dann einige zusätzliche Methoden hinzufügen möchten? Ist das ein Dekorateur oder ein Adapter?
Donquijote

198

Wie Bills Antwort sagt, sind ihre Anwendungsfälle unterschiedlich .

So sind ihre Strukturen.

  • Proxy und Decorator haben beide dieselbe Schnittstelle wie ihre umschlossenen Typen, aber der Proxy erstellt eine Instanz unter der Haube, während der Decorator eine Instanz im Konstruktor übernimmt.

  • Adapter und Fassade haben beide eine andere Oberfläche als das, was sie einwickeln. Der Adapter leitet sich jedoch von einer vorhandenen Schnittstelle ab, während die Fassade eine neue Schnittstelle erstellt.

  • Bridge und Adapter zeigen beide auf einen vorhandenen Typ. Die Brücke zeigt jedoch auf einen abstrakten Typ, und der Adapter zeigt möglicherweise auf einen konkreten Typ. Über die Bridge können Sie die Implementierung zur Laufzeit koppeln, während dies beim Adapter normalerweise nicht der Fall ist.


30
Ihre Antwort in Kombination mit Bills fasst 5 Kapitel von Design Patterns sehr gut zusammen. Man könnte sie eine übergeordnete (sprich: einfachere) Schnittstelle zum Buch nennen.
Jonas Eicher

54

Meine Sicht auf das Thema.

Alle vier Muster haben viel gemeinsam, alle vier werden manchmal informell als Wrapper oder Wrapper-Muster bezeichnet. Alle verwenden Komposition, umbrechen den Betreff und delegieren die Ausführung irgendwann an den Betreff. Ordnen Sie einen Methodenaufruf einem anderen zu. Sie ersparen dem Kunden die Notwendigkeit, ein anderes Objekt erstellen und alle relevanten Daten kopieren zu müssen. Mit Bedacht sparen sie Speicher und Prozessor.

Durch die Förderung der losen Kopplung wird der einst stabile Code weniger unvermeidlichen Änderungen ausgesetzt und für andere Entwickler besser lesbar.

Adapter

Der Adapter passt das Subjekt (Adaptee) an eine andere Schnittstelle an. Auf diese Weise können wir Objekte hinzufügen, die einer Sammlung von nominell unterschiedlichen Typen hinzugefügt werden sollen.

Der Adapter stellt dem Client nur relevante Methoden zur Verfügung, kann alle anderen einschränken und Verwendungsabsichten für bestimmte Kontexte offenlegen, z. B. die Anpassung der externen Bibliothek, und lässt sie weniger allgemein und stärker auf unsere Anwendungsanforderungen ausgerichtet erscheinen. Adapter verbessern die Lesbarkeit und Selbstbeschreibung unseres Codes.

Adapter schützen ein Team vor flüchtigem Code anderer Teams. ein lebensrettendes Werkzeug im Umgang mit Offshore-Teams ;-)

Weniger erwähnt dient es dazu, zu verhindern, dass die Fachklasse die Anmerkungen überschreitet. Bei so vielen Frameworks, die auf Anmerkungen basieren, wird diese Verwendung wichtiger als je zuvor.

Der Adapter hilft dabei, die Java-Beschränkung nur einer einzelnen Vererbung zu umgehen. Es kann mehrere Adaptees unter einem Umschlag kombinieren, was den Eindruck einer Mehrfachvererbung erweckt.

Code weise ist der Adapter "dünn". Es sollte der adaptee-Klasse nicht viel Code hinzufügen, außer einfach die adaptee-Methode aufzurufen und gelegentlich Datenkonvertierungen durchzuführen, die für solche Aufrufe erforderlich sind.

Es gibt nicht viele gute Adapterbeispiele in JDK oder Basisbibliotheken. Anwendungsentwickler erstellen Adapter, um Bibliotheken an anwendungsspezifische Schnittstellen anzupassen.

Dekorateur

Decorator delegiert nicht nur, ordnet nicht nur eine Methode einer anderen zu, sie tun mehr, sie ändern das Verhalten einiger Subjektmethoden, es kann entscheiden, überhaupt keine Subjektmethode aufzurufen, an ein anderes Objekt zu delegieren, ein Hilfsobjekt.

Dekorateure fügen verpackten Objekten normalerweise (transparent) Funktionen wie Protokollierung, Verschlüsselung, Formatierung oder Komprimierung des Betreffs hinzu. Diese neue Funktionalität kann viel neuen Code bringen. Daher sind Dekorateure normalerweise viel „dicker“ als Adapter.

Der Dekorateur muss eine Unterklasse der Benutzeroberfläche des Subjekts sein. Sie können transparent anstelle der Themen verwendet werden. Siehe BufferedOutputStream, es ist immer noch OutputStream und kann als solches verwendet werden. Das ist ein großer technischer Unterschied zu Adaptern.

Lehrbuchbeispiele der gesamten Dekorateurfamilie sind in JDK - dem Java IO - leicht zu finden. Alle Klassen wie BufferedOutputStream , FilterOutputStream und ObjectOutputStream sind Dekoratoren von OutputStream . Sie können mit Zwiebeln überzogen werden, wobei ein Dekorateur erneut dekoriert wird, wodurch mehr Funktionalität hinzugefügt wird.

Proxy

Proxy ist kein typischer Wrapper. Das umschlossene Objekt, das Proxy-Subjekt, ist zum Zeitpunkt der Proxy-Erstellung möglicherweise noch nicht vorhanden. Proxy erstellt es häufig intern. Es kann sich um ein schweres Objekt handeln, das bei Bedarf erstellt wird, oder es handelt sich um ein Remote-Objekt in einer anderen JVM oder einem anderen Netzwerkknoten und sogar um ein Nicht-Java-Objekt, eine Komponente im nativen Code. Es muss überhaupt nicht umbrochen oder an ein anderes Objekt delegiert werden.

Die typischsten Beispiele sind Remote-Proxys, Initialisierer für schwere Objekte und Zugriffsproxys.

  • Remote-Proxy - Betreff befindet sich auf einem Remote-Server, einer anderen JVM oder sogar einem Nicht-Java-System. Proxy übersetzt Methodenaufrufe in RMI / REST / SOAP-Aufrufe oder was auch immer erforderlich ist, um den Client vor dem Kontakt mit der zugrunde liegenden Technologie zu schützen.

  • Lazy Load Proxy - Initialisieren Sie das Objekt nur bei der ersten oder ersten intensiven Nutzung vollständig.

  • Access Proxy - Kontrolliert den Zugriff auf den Betreff.

Fassade

Die Fassade ist eng mit dem Gestaltungsprinzip des geringsten Wissens (Gesetz des Demeters) verbunden. Fassade ist Adapter sehr ähnlich. Sie wickeln beide ein, sie ordnen ein Objekt einem anderen zu, aber sie unterscheiden sich in der Absicht. Die Fassade glättet die komplexe Struktur eines Subjekts und das komplexe Objektdiagramm und vereinfacht den Zugriff auf eine komplexe Struktur.

Die Fassade umhüllt eine komplexe Struktur und bietet eine flache Schnittstelle. Dies verhindert, dass das Client-Objekt inneren Beziehungen in der Subjektstruktur ausgesetzt wird, wodurch eine lose Kopplung gefördert wird.

Brücke

Komplexere Variante des Adaptermusters, bei der nicht nur die Implementierung variiert, sondern auch die Abstraktion. Es fügt der Delegation eine weitere Indirektion hinzu. Die zusätzliche Delegation ist die Brücke. Es entkoppelt den Adapter sogar von der Anpassung der Schnittstelle. Es erhöht die Komplexität mehr als jedes andere Verpackungsmuster. Wenden Sie es daher mit Vorsicht an.

Unterschiede in den Konstruktoren

Musterunterschiede sind auch bei der Betrachtung ihrer Konstruktoren offensichtlich.

  • Der Proxy umschließt kein vorhandenes Objekt. Es gibt kein Thema im Konstruktor.

  • Decorator und Adapter umschließen bereits vorhandene Objekte, und diese werden normalerweise
    im Konstruktor bereitgestellt.

  • Der Fassadenkonstruktor verwendet das Stammelement eines gesamten Objektdiagramms, ansonsten sieht es genauso aus wie der Adapter.

Beispiel aus dem wirklichen Leben - JAXB Marshalling Adapter . Zweck dieses Adapters ist die Zuordnung einer einfachen flachen Klasse zu einer komplexeren Struktur, die extern erforderlich ist, und um zu verhindern, dass die Subjektklasse mit übermäßigen Anmerkungen "verschmutzt" wird.


30

Viele der GoF-Muster überschneiden sich stark. Sie alle bauen auf der Kraft des Polymorphismus auf und unterscheiden sich manchmal nur in ihrer Absicht. (Strategie gegen Staat)

Mein Verständnis von Mustern hat sich nach dem Lesen von Head First Design Patterns um das 100-fache erhöht .

Ich empfehle es sehr!


9

Alle guten Antworten von Experten haben bereits erklärt, wofür jedes Muster steht.

Ich werde wichtige Punkte dekorieren .

Dekorateur:

  1. Fügen Sie dem Objekt zur Laufzeit Verhalten hinzu . Vererbung ist der Schlüssel, um diese Funktionalität zu erreichen, was sowohl Vor- als auch Nachteil dieses Musters ist.
  2. Es ändert das Verhalten der Schnittstelle.

zB (mit Verkettung): java.ioPaketklassen, die sich auf InputStream& OutputStreaminterfaces beziehen

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

Proxy:

  1. Verwenden Sie es für die verzögerte Initialisierung, Leistungsverbesserung durch Zwischenspeichern des Objekts und Steuern des Zugriffs auf den Client / Anrufer . Es kann ein alternatives Verhalten bieten oder ein reales Objekt aufrufen. Während dieses Vorgangs wird möglicherweise ein neues Objekt erstellt.
  2. Im Gegensatz zu Decorator , mit dem Objekte verkettet werden können, lässt Proxy keine Verkettung zu.

zB: java.rmiPaketklassen.

Adapter:

  1. Es ermöglicht zwei nicht miteinander verbundenen Schnittstellen, über die verschiedenen Objekte zusammenzuarbeiten und möglicherweise dieselbe Rolle zu spielen.
  2. Es ändert die ursprüngliche Schnittstelle .

zB java.io.InputStreamReader( InputStreamgibt a zurück Reader)

Brücke:

  1. Es ermöglicht, dass sowohl Abstraktionen als auch Implementierungen unabhängig voneinander variieren .
  2. Es verwendet Komposition über Vererbung .

zB Sammlungsklassen in java.util. Listimplementiert von ArrayList.

Wichtige Hinweise:

  1. Der Adapter bietet eine andere Schnittstelle zu seinem Thema. Proxy bietet die gleiche Schnittstelle. Decorator bietet eine erweiterte Oberfläche.
  2. Der Adapter ändert die Benutzeroberfläche eines Objekts, Decorator erweitert die Verantwortlichkeiten eines Objekts.
  3. Decorator und Proxy haben unterschiedliche Zwecke, aber ähnliche Strukturen
  4. Mit dem Adapter funktionieren die Dinge, nachdem sie entworfen wurden. Bridge lässt sie arbeiten, bevor sie es sind.
  5. Bridge wurde von vornherein so konzipiert, dass Abstraktion und Implementierung unabhängig voneinander variieren können. Der Adapter wird nachgerüstet, damit nicht verwandte Klassen zusammenarbeiten
  6. Mit Decorator können Sie Objekten Verantwortlichkeiten ohne Unterklassen hinzufügen.

Schauen Sie sich großartige SE-Fragen / Artikel zu Beispielen für verschiedene Designmuster an

Wann sollte das Dekorationsmuster verwendet werden?

Wann verwenden Sie das Brückenmuster? Wie unterscheidet es sich vom Adaptermuster?

Unterschiede zwischen Proxy- und Decorator-Muster


8

Sie sind ziemlich ähnlich und die Linien zwischen ihnen sind ziemlich grau. Ich schlage vor, Sie lesen die Einträge Proxy Pattern und Decorator Pattern im c2-Wiki.

Die Einträge und Diskussionen dort sind recht umfangreich und sie verlinken auch auf andere relevante Artikel. Das c2-Wiki eignet sich übrigens hervorragend, wenn man sich über die Nuancen zwischen verschiedenen Mustern wundert.

Um die c2-Einträge zusammenzufassen, würde ich sagen, dass ein Dekorateur das Verhalten hinzufügt / ändert, aber ein Proxy hat mehr mit der Zugriffskontrolle zu tun (verzögerte Instanziierung, Remotezugriff, Sicherheit usw.). Aber wie gesagt, die Linien zwischen ihnen sind grau, und ich sehe Verweise auf Proxys, die leicht als Dekorateure angesehen werden können und umgekehrt.


4

Alle vier Muster beinhalten das Umschließen des inneren Objekts / der inneren Klasse mit dem äußeren, so dass sie strukturell sehr ähnlich sind. Ich würde den Unterschied durch den Zweck skizzieren:

  • Proxy kapselt den Zugriff von außen nach innen.
  • Der Dekorateur verändert oder erweitert das Verhalten von innen nach außen.
  • Der Adapter konvertiert die Schnittstelle von innen nach außen.
  • Die Brücke trennt einen unveränderlichen Teil des Verhaltens (außen) vom variablen oder plattformabhängigen Teil (innen).

Und durch Schnittstellenvariationen zwischen inneren und äußeren Objekten:

  • in Proxy Schnittstellen sind die gleichen.
  • in Decorator Schnittstellen sind die gleichen.
  • in Adapter Schnittstellen sind formal unterschiedlich, erfüllen aber den gleichen Zweck.
  • in Bridge- Schnittstellen unterscheiden sich konzeptionell.

4

Dies ist ein Zitat aus Head First Design Patterns

Definitionen gehören zum Buch. Beispiele gehören mir.

Dekorateur - Ändert die Benutzeroberfläche nicht, fügt aber Verantwortung hinzu. Angenommen, Sie haben eine Fahrzeugschnittstelle. Wenn Sie diese für verschiedene Fahrzeugmodelle (s, sv, sl) implementieren, müssen Sie möglicherweise mehr Verantwortung hinzufügen für einige Modelle . Wie hat Schiebedach, Airbag etc ..

Adapter - Konvertiert eine Schnittstelle in eine andere. Sie haben eine Autoschnittstelle und möchten, dass sie sich wie ein Jeep verhält. Also nimmst du das Auto, modifizierst es und verwandelst dich in einen Jeep. Da ist es kein richtiger Jeep. Aber wirkt wie ein Jeep.

Fassade - Vereinfacht die Benutzeroberfläche. Angenommen, Sie haben Auto-, Flugzeug- und Schiffsschnittstellen. Eigentlich brauchen Sie nur eine Klasse, die Leute von einem Ort zum anderen schickt. Sie möchten, dass die Fassade entscheidet, welches Fahrzeug verwendet wird. Dann sammeln Sie alle diese Schnittstellenreferenzen unter einem Dach und lassen es entscheiden / delegieren, um es einfach zu halten.

Head First: "Eine Fassade vereinfacht nicht nur eine Schnittstelle, sondern entkoppelt einen Client von einem Teilsystem von Komponenten. Fassaden und Adapter können mehrere Klassen umschließen, aber eine Fassade soll vereinfacht werden, während ein Adapter die Schnittstelle in etwas anderes konvertieren soll. ""


1

Ich benutze es ziemlich oft, wenn ich Webdienste konsumiere. Das Proxy-Muster sollte wahrscheinlich in etwas Pragmatischeres wie "Wrapper-Muster" umbenannt werden. Ich habe auch eine Bibliothek, die ein Proxy für MS Excel ist. Es macht es sehr einfach, Excel zu automatisieren, ohne sich um Hintergrunddetails wie das kümmern zu müssen Version ist installiert (falls vorhanden).


Wäre das nicht einfach das Adaptermuster?
Charles Graham

1
Ein Webdienst wird von einem Proxy verwendet, während das Adaptermuster eher für die Konvertierung oder Übersetzung von Daten von einem Formular in ein anderes verwendet wird.
hmcclungiii

1

Bei der Detailimplementierung finde ich einen Unterschied zwischen Proxy und Decorator, Adapter, Fassade ... Bei der allgemeinen Implementierung dieser Muster gibt es ein Zielobjekt, das von einem umschließenden Objekt umschlossen wird. Der Client verwendet ein umschließendes Objekt anstelle eines Zielobjekts. Und das Zielobjekt spielt tatsächlich eine wichtige Rolle bei einigen Methoden zum Einschließen von Objekten.

Im Fall von Proxy kann das einschließende Objekt jedoch einige Methoden selbst abspielen. Es initialisiert nur das Zielobjekt, wenn der Client einige Methoden aufruft, an denen das Zielobjekt teilnehmen muss. Dies ist eine verzögerte Initialisierung. Bei anderen Mustern basiert das umschließende Objekt virtuell auf dem Zielobjekt. Das Zielobjekt wird also immer zusammen mit dem Einschließen des Objekts in Konstruktoren / Setter initialisiert.

Eine andere Sache ist, dass ein Proxy genau das tut, was ein Ziel tut, während andere Muster dem Ziel mehr Funktionalität hinzufügen.


1

Ich möchte der Antwort von Bill Karwing Beispiele hinzufügen (was übrigens großartig ist). Ich füge auch einige wichtige Unterschiede bei der Implementierung hinzu, die meiner Meinung nach fehlen

Zitierte Teile stammen aus der Antwort von [ https://stackoverflow.com/a/350471/1984346] (Bill Karwing)

Proxy, Decorator, Adapter und Bridge sind Variationen beim "Umschließen" einer Klasse. Ihre Verwendung ist jedoch unterschiedlich.

  • Proxy kann verwendet werden, wenn Sie ein Objekt verzögert instanziieren oder die Tatsache verbergen möchten, dass Sie einen Remotedienst aufrufen, oder den Zugriff auf das Objekt steuern möchten.

ProxyClass und ObjectClass, die als Proxy fungieren, sollten dieselbe Schnittstelle implementieren, damit sie austauschbar sind

Beispiel - Proxy teures Objekt

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 wird auch als "Smart Proxy" bezeichnet. Dies wird verwendet, wenn Sie einem Objekt Funktionen hinzufügen möchten, jedoch nicht, indem Sie den Typ dieses Objekts erweitern. Dies ermöglicht Ihnen dies zur Laufzeit.

DecoratorClass sollte (könnte) eine erweiterte Schnittstelle von ObjectClass implementieren. Die ObjectClass könnte also durch DecoratorClass ersetzt werden, aber nicht umgekehrt.

Beispiel - Hinzufügen von Zusatzfunktionen

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 { ... }
  • Der Adapter wird verwendet, wenn Sie eine abstrakte Schnittstelle haben und diese Schnittstelle einem anderen Objekt zuordnen möchten, das eine ähnliche funktionale Rolle, aber eine andere Schnittstelle hat.

Implementierungsunterschiede Proxy, Decorator, Adapter

Der Adapter bietet eine andere Schnittstelle zu seinem Thema. Proxy bietet die gleiche Schnittstelle. Decorator bietet eine erweiterte Oberfläche.

  • Bridge ist Adapter sehr ähnlich, aber wir nennen es Bridge, wenn Sie sowohl die abstrakte Schnittstelle als auch die zugrunde liegende Implementierung definieren. Das heißt, Sie passen sich nicht an Legacy-Code oder Code von Drittanbietern an, Sie sind der Designer des gesamten Codes, aber Sie müssen in der Lage sein, verschiedene Implementierungen auszutauschen.

  • Facade ist eine übergeordnete (sprich: einfachere) Schnittstelle zu einem Subsystem einer oder mehrerer Klassen. Angenommen, Sie haben ein komplexes Konzept, für dessen Darstellung mehrere Objekte erforderlich sind. Das Vornehmen von Änderungen an dieser Gruppe von Objekten ist verwirrend, da Sie nicht immer wissen, welches Objekt die Methode hat, die Sie aufrufen müssen. Dies ist die Zeit, um eine Fassade zu schreiben, die allgemeine Methoden für alle komplexen Vorgänge bietet, die Sie für die Sammlung von Objekten ausführen können. Beispiel: Ein Domain Model für eine Schule Abschnitt, mit Methoden wie countStudents(), reportAttendance(), assignSubstituteTeacher(), und so weiter.

Die meisten Informationen in dieser Antwort stammen von https://sourcemaking.com/design_patterns , die ich als hervorragende Ressource für Entwurfsmuster empfehle .


0

Ich glaube, dass Code klare Ideen liefert (um auch andere Antworten zu ergänzen). Siehe unten (Konzentrieren Sie sich auf die Typen, die eine Klasse implementiert und umschließt).

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

Entwurfsmuster sind keine Mathematik, sondern eine Kombination aus Kunst und Softwareentwicklung. Es gibt nichts Vergleichbares für diese Anforderung, dass Sie Proxy, Bridge usw. verwenden müssen. Entwurfsmuster werden erstellt, um die Probleme zu lösen. Wenn Sie ein Designproblem antizipieren, verwenden Sie es. Basierend auf der Erfahrung werden Sie für ein bestimmtes Problem wissen, welches Muster verwendet werden soll. Wenn Sie sich mit soliden Entwurfsprinzipien auskennen, hätten Sie ein Entwurfsmuster implementiert, ohne zu wissen, dass es sich um ein Muster handelt. Ein häufiges Beispiel sind Statergie und Fabrikmuster

Konzentrieren Sie sich daher mehr auf solide Desighn-Prinzipien, Clean-Coding-Prinzipien und ttd


Stimmen Sie zu, obwohl es die Frage nicht beantwortet.
Leon
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.