Czym różnią się wzory proxy, dekoratora, adaptera i mostka?

403

Patrzyłem na wzór proxy i wydaje mi się to okropnie podobne do wzorów Decorator, Adapter i Bridge. Czy coś nie rozumiem? Co za różnica? Dlaczego miałbym używać wzorca proxy w porównaniu do innych? Jak korzystałeś z nich w przeszłości w projektach z prawdziwego świata?

Charles Graham
źródło
4
Często istnieją wzorce, które wyglądają bardzo podobnie, ale różnią się intencją (przychodzą mi na myśl strategie i wzorce stanowe). Myślę, że często wynika to z faktu, że wzorce projektowe oparte są na wspólnych solidnych zasadach projektowych.
Jason Down
5
Te cztery wzorce mają dokładnie takie same szczegóły implementacji. Wersety stanowe Strategia może być co najmniej podsumowana jako pełne wersety stanowe bezstanowe (w przeważającej części). Często strategia to tylko wstrzyknięcie metody, w której wzorzec stanu używa interfejsu, aby wykonać więcej niż wyodrębnić wywołanie metody. Strategia to także hack umożliwiający funkcjonalne programowanie w świecie OO.
Charles Graham

Odpowiedzi:

648

Proxy, dekorator, adapter i mostek są odmianami „zawijania” klasy. Ale ich zastosowania są różne.

  • Proxy może być użyte, gdy chcesz leniwie utworzyć instancję obiektu lub ukryć fakt, że dzwonisz do usługi zdalnej lub kontrolować dostęp do obiektu.

  • Dekorator jest również nazywany „Smart Proxy”. Jest to używane, gdy chcesz dodać funkcjonalność do obiektu, ale nie przez rozszerzenie typu tego obiektu. To pozwala ci to zrobić w czasie wykonywania.

  • Adapter jest używany, gdy masz interfejs abstrakcyjny i chcesz zmapować ten interfejs na inny obiekt, który ma podobną rolę funkcjonalną, ale inny interfejs.

  • Bridge jest bardzo podobny do Adaptera, ale nazywamy go Bridge, gdy definiujesz zarówno interfejs abstrakcyjny, jak i podstawową implementację. Oznacza to, że nie dostosowujesz się do jakiegoś starszego kodu lub kodu innej firmy, jesteś projektantem całego kodu, ale musisz mieć możliwość wymiany różnych implementacji.

  • Fasada to interfejs wyższego poziomu (czytaj: prostszy) do podsystemu jednej lub więcej klas. Załóżmy, że masz złożoną koncepcję, która wymaga reprezentacji wielu obiektów. Wprowadzanie zmian w tym zestawie obiektów jest mylące, ponieważ nie zawsze wiesz, który obiekt ma metodę, którą musisz wywołać. Nadszedł czas, aby napisać fasadę, która zapewnia metody wysokiego poziomu dla wszystkich złożonych operacji, jakie można wykonać na zbiorze obiektów. Przykład: Domain Wzór sekcji szkolnej metod, takich jak countStudents(), reportAttendance(), assignSubstituteTeacher()i tak dalej.

Bill Karwin
źródło
7
Dobra odpowiedź. Czy warto dodać kilka przykładów tego, gdzie widzisz go na wolności? np. klasy proxy w usługach sieciowych. +1 ode mnie
Rob Cooper
5
@Rob: dzięki, ale wolę, aby ta odpowiedź była krótka i słodka. Zachęcam do napisania kolejnej odpowiedzi z przykładami na wolności!
Bill Karwin,
8
@RobertDailey Decorator jest również dobry, aby uniknąć hierarchii typów poza kontrolą. Załóżmy na przykład , że masz okno w graficznym interfejsie użytkownika i chcesz mieć opcjonalne paski przewijania. Możesz mieć klasy Window, VScrollWindow, HScrollWindow i VHScrollWindow lub możesz utworzyć dekoratory VScroll i HScroll w systemie Windows.
Eva
1
@RobertDailey, Dekorator to kompozycja.
Bill Karwin
1
A jeśli chcesz powielić interfejs zawiniętego obiektu 1: 1, a następnie dodać kilka dodatkowych metod? Czy to dekorator czy adapter?
donquixote
198

Jak mówi odpowiedź Billa, ich przypadki użycia są różne .

Podobnie jak ich struktury.

  • Zarówno proxy, jak i dekorator mają taki sam interfejs, jak ich opakowane typy, ale proxy tworzy instancję pod maską, podczas gdy dekorator bierze instancję w konstruktorze.

  • Zarówno adapter, jak i fasada mają inny interfejs niż to, co obejmują. Ale adapter wywodzi się z istniejącego interfejsu, podczas gdy fasada tworzy nowy interfejs.

  • Mostek i adapter wskazują na istniejący typ. Ale most będzie wskazywał na typ abstrakcyjny, a adapter może wskazywać na konkretny typ. Mostek pozwoli ci sparować implementację w czasie wykonywania, podczas gdy adapter zwykle nie.

Merlyn Morgan-Graham
źródło
30
Twoja odpowiedź w połączeniu z Billa bardzo ładnie podsumowuje 5 rozdziałów Wzorów projektowych. Można by je nazwać interfejsem nadrzędnym (czytaj: prostszym) do książki.
Jonas Eicher
54

Moje zdanie na ten temat.

Wszystkie cztery wzorce mają ze sobą wiele wspólnego, wszystkie cztery są czasem nieformalnie nazywane opakowaniami lub wzorami opakowań. Wszyscy używają kompozycji, zawijania tematu i delegowania wykonania do tematu w pewnym momencie, odwzorowując jedno wywołanie metody na inne. Oszczędzają klientowi konieczności konstruowania innego obiektu i kopiowania wszystkich istotnych danych. Jeśli są używane mądrze, oszczędzają pamięć i procesor.

Promując luźne sprzęganie, sprawiają, że niegdyś stabilny kod jest mniej narażony na nieuniknione zmiany i lepiej czytelny dla innych programistów.

Adapter

Adapter dostosowuje temat (adapttee) do innego interfejsu. W ten sposób możemy dodać obiekt do zbioru nominalnie różnych typów.

Adapter udostępnia klientowi tylko odpowiednie metody, może ograniczyć wszystkie inne, ujawniając zamiary użytkowania w określonych kontekstach, takie jak adaptacja zewnętrznej biblioteki, sprawiając, że wydaje się ona mniej ogólna i bardziej skoncentrowana na potrzebach naszej aplikacji. Adaptery zwiększają czytelność i własny opis naszego kodu.

Adaptery chronią jeden zespół przed niestabilnym kodem od innych zespołów; narzędzie ratujące życie w kontaktach z zespołami offshore ;-)

Mniej wspomniany ma na celu zapobieganie nadmiarowi adnotacji w klasie przedmiotów. Przy tak wielu ramach opartych na adnotacjach staje się to ważniejsze niż kiedykolwiek.

Adapter pomaga ominąć ograniczenie Java tylko jednego dziedziczenia. Może łączyć kilka adapterów pod jedną kopertą, co daje wrażenie wielokrotnego dziedziczenia.

Pod względem kodu adapter jest „cienki”. Nie powinien dodawać zbyt wiele kodu do klasy adapttee, oprócz zwykłego wywoływania metody adapttee i sporadycznych konwersji danych niezbędnych do wykonywania takich wywołań.

W JDK lub bibliotekach podstawowych nie ma wielu dobrych przykładów adapterów. Twórcy aplikacji tworzą Adaptery, aby dostosować biblioteki do interfejsów specyficznych dla aplikacji.

Dekorator

Dekorator nie tylko deleguje, nie tylko mapuje jedną metodę na drugą, ale robi więcej, modyfikuje zachowanie niektórych metod przedmiotowych, może zdecydować, że w ogóle nie wywoła metody podmiotowej, deleguje do innego obiektu, obiektu pomocnika.

Dekoratorzy zazwyczaj dodają (przezroczystą) funkcjonalność do zawiniętego obiektu, taką jak rejestrowanie, szyfrowanie, formatowanie lub kompresja obiektu. Ta nowa funkcjonalność może przynieść wiele nowego kodu. Dlatego dekoratorzy są zwykle o wiele „grubsi” niż Adaptery.

Dekorator musi być podklasą interfejsu podmiotu. Można ich używać w sposób przejrzysty zamiast tematów. Patrz BufferedOutputStream, nadal jest OutputStream i może być używany jako taki. Jest to główna różnica techniczna w stosunku do adapterów.

Przykłady podręczników dla całej rodziny dekoratorów znajdują się w JDK - Java IO. Wszystkie klasy, takie jak BufferedOutputStream , FilterOutputStream i ObjectOutputStream, są dekoratorami OutputStream . Mogą być warstwami cebuli, gdzie jeden dekorator jest ponownie dekorowany, co zwiększa funkcjonalność.

Pełnomocnik

Serwer proxy nie jest typowym opakowaniem. Zawinięty obiekt, podmiot proxy, może jeszcze nie istnieć w momencie tworzenia proxy. Serwer proxy często tworzy go wewnętrznie. Może to być ciężki obiekt tworzony na żądanie lub obiekt zdalny w innej maszynie JVM lub w innym węźle sieciowym, a nawet obiekt inny niż Java, składnik w natywnym kodzie. Nie musi wcale owijać ani delegować do innego obiektu.

Najbardziej typowymi przykładami są zdalne proxy, inicjatory ciężkich obiektów i proxy dostępu.

  • Remote Proxy - podmiot znajduje się na zdalnym serwerze, innym JVM lub nawet w systemie innym niż Java. Serwer proxy tłumaczy wywołania metod na wywołania RMI / REST / SOAP lub cokolwiek jest potrzebne, chroniąc klienta przed narażeniem na podstawowe technologie.

  • Lazy Load Proxy - pełna inicjalizacja obiektu tylko przy pierwszym użyciu lub pierwszym intensywnym użyciu.

  • Access Proxy - kontroluj dostęp do tematu.

Fasada

Fasada jest ściśle związana z zasadą projektowania najmniejszej wiedzy (Law of Demeter). Fasada jest bardzo podobna do adaptera. Obaj się zawijają, oboje mapują jeden obiekt na inny, ale różnią się intencją. Fasada spłaszcza złożoną strukturę obiektu, złożony wykres obiektu, upraszczając dostęp do złożonej struktury.

Fasada otacza złożoną strukturę, zapewniając płaski interfejs. Zapobiega to narażeniu obiektu klienta na relacje wewnętrzne w strukturze podmiotu, a tym samym sprzyja luźnemu łączeniu.

Most

Bardziej złożony wariant wzorca adaptera, w którym różni się nie tylko implementacja, ale również abstrakcja. Dodaje jeszcze jedno pośrednie przekazanie uprawnień. Dodatkowa delegacja to most. Oddziela adapter nawet od dostosowania interfejsu. Zwiększa złożoność bardziej niż jakikolwiek inny wzór owijania, więc aplikuj ostrożnie.

Różnice w konstruktorach

Różnice w strukturze są również widoczne, gdy patrzymy na ich konstruktorów.

  • Serwer proxy nie zawija istniejącego obiektu. Konstruktor nie zawiera tematu.

  • Dekorator i adapter owijają już istniejący obiekt, i taki jest zwykle
    dostarczany w konstruktorze.

  • Konstruktor fasad pobiera element główny z wykresu całego obiektu, w przeciwnym razie wygląda tak samo jak Adapter.

Przykład z życia - adapter Marshalling JAXB . Celem tego adaptera jest odwzorowanie prostej klasy płaskiej na bardziej złożoną strukturę wymaganą zewnętrznie i zapobieganie „zanieczyszczeniu” klasy przedmiotu za pomocą nadmiernych adnotacji.

Espinosa
źródło
30

Wiele wzorców GoF nakłada się na siebie. Wszystkie są zbudowane na sile polimorfizmu i czasami naprawdę różnią się tylko intencją. (strategia vs. stan)

Moje zrozumienie wzorów wzrosło 100-krotnie po przeczytaniu Head First Design Patterns .

Gorąco polecam!

Dina
źródło
9

Wszystkie dobre odpowiedzi ekspertów wyjaśniły już, co oznacza każdy wzór.

Będę ozdobić kluczowych punktów.

Dekorator:

  1. Dodaj zachowanie do obiektu w czasie wykonywania . Dziedziczenie jest kluczem do osiągnięcia tej funkcjonalności, która jest zarówno zaletą, jak i wadą tego wzoru.
  2. Zmienia zachowanie interfejsu.

na przykład (z łańcuchowym): java.iozajęcia związane z pakietów InputStreami OutputStreaminterfejsów

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

Pełnomocnik:

  1. Użyj go do leniwej inicjalizacji, poprawy wydajności poprzez buforowanie obiektu i kontrolowanie dostępu do klienta / rozmówcy . Może zapewnić alternatywne zachowanie lub wywołać prawdziwy obiekt. Podczas tego procesu może utworzyć nowy Obiekt.
  2. W przeciwieństwie do programu Decorator , który umożliwia łączenie obiektów, serwer proxy nie umożliwia łączenia.

np .: java.rmiklasy pakietów.

Adapter:

  1. Pozwala dwóm niepowiązanym interfejsom współpracować ze sobą przez różne obiekty , prawdopodobnie grając tę ​​samą rolę.
  2. Zmienia oryginalny interfejs .

np. java.io.InputStreamReader( InputStreamzwraca a Reader)

Most:

  1. Pozwala to na niezależne zmienianie zarówno abstrakcji, jak i implementacji .
  2. Wykorzystuje kompozycję zamiast dziedziczenia .

np. klasy kolekcji w java.util. Listrealizowane przez ArrayList.

Kluczowe uwagi:

  1. Adapter zapewnia inny interfejs dla swojego tematu. Serwer proxy zapewnia ten sam interfejs. Decorator zapewnia ulepszony interfejs.
  2. Adapter zmienia interfejs obiektu, Dekorator zwiększa obowiązki obiektu.
  3. Dekorator i serwer proxy mają różne cele, ale podobne struktury
  4. Adapter sprawia, że ​​rzeczy działają po ich zaprojektowaniu; Bridge sprawia, że ​​pracują zanim będą.
  5. Bridge został zaprojektowany z góry, aby abstrakcja i implementacja różniły się niezależnie. Adapter został zmodernizowany, aby klasy niepowiązane ze sobą współpracowały
  6. Program Decorator umożliwia dodawanie obowiązków do obiektów bez tworzenia podklas.

Rzuć okiem na świetne pytania / artykuły dotyczące SE dotyczące przykładów różnych wzorców projektowych

Kiedy stosować wzór dekoratora?

Kiedy używasz wzorca mostu? Czym różni się od wzorca adaptera?

Różnice między wzorem proxy a dekoratorem

Ravindra babu
źródło
8

Są dość podobne, a linie między nimi są dość szare. Sugeruję przeczytanie wpisów Wzorca proxy i Wzorca dekoratora na wiki wiki c2.

Wpisy i dyskusje są dość obszerne, a także zawierają linki do innych odpowiednich artykułów. Nawiasem mówiąc, wiki c2 jest doskonała, gdy zastanawiasz się nad niuansami między różnymi wzorami.

Podsumowując wpisy C2, powiedziałbym, że dekorator dodaje / zmienia zachowanie, ale proxy ma więcej wspólnego z kontrolą dostępu (leniwa instancja, zdalny dostęp, bezpieczeństwo itp.). Ale, jak powiedziałem, linie między nimi są szare i widzę odniesienia do serwerów proxy, które można łatwo postrzegać jako dekoratorów i odwrotnie.

Bent André Solheim
źródło
4

Wszystkie cztery wzory wymagają zawijania wewnętrznego obiektu / klasy zewnętrznym, więc są bardzo podobne strukturalnie. Chciałbym przedstawić różnicę według celu:

  • Proxy hermetyzuje dostęp od zewnętrznego do wewnętrznego.
  • Dekorator modyfikuje lub rozszerza zachowanie wnętrza z zewnętrzem.
  • Adapter konwertuje interfejs z wewnętrznego na zewnętrzny.
  • Bridge oddziela niezmienną część zachowania (zewnętrzną) od zmiennej lub zależną od platformy (wewnętrzną).

I przez zmianę interfejsu między obiektami wewnętrznymi i zewnętrznymi:

  • w Proxy interfejsie są takie same.
  • w dekorator interfejsy są takie same.
  • w Adapter interfejsów różnią się formalnie, ale spełniają ten sam cel.
  • Interfejsy w Bridge są różne pod względem koncepcyjnym.
Alexey
źródło
4

To jest cytat z Head First Design Patterns

Definicje należą do książki. Przykłady należą do mnie.

Dekorator - nie zmienia interfejsu, ale dodaje odpowiedzialność. Załóżmy, że masz interfejs samochodu. Po wdrożeniu tego dla innego modelu samochodu (s, sv, sl) może być konieczne dodanie większej odpowiedzialności za niektóre modele. Podobnie jak szyberdach, poduszka powietrzna itp.

Adapter - Konwertuje jeden interfejs na inny. Masz interfejs samochodu i chciałbyś, aby działał jak jeep. Więc weź samochód, zmodyfikuj go i zamień w jeepa. Ponieważ nie jest to prawdziwy jeep. Ale działa jak jeep.

Fasada - upraszcza interfejs. Załóżmy, że masz interfejs samochodu, samolotu i statku. Właściwie wszystko, czego potrzebujesz, to klasa, która wysyła ludzi z jednej lokalizacji do drugiej. Chcesz, aby fasada decydowała, jakiego pojazdu użyć. Następnie zbierasz wszystkie odniesienia do interfejsów pod 1 parasolem i pozwalasz decydować / delegować, aby było to proste.

Po pierwsze: „Fasada nie tylko upraszcza interfejs, ale także oddziela klienta od podsystemu komponentów. Fasady i adaptery mogą owijać wiele klas, ale intencją fasady jest uproszczenie, podczas gdy adapter ma przekonwertować interfejs na coś innego. „

Teoman Shipahi
źródło
1

Używam go dość często podczas korzystania z usług internetowych. Nazwa wzoru proxy powinna prawdopodobnie zostać przemianowana na coś bardziej pragmatycznego, na przykład „Wzorzec opakowania”. Mam również bibliotekę, która jest serwerem proxy do MS Excel. Ułatwia to automatyzację programu Excel, bez martwienia się o szczegóły tła, takie jak wersja jest zainstalowana (jeśli istnieje).

hmcclungiii
źródło
Czy to nie byłby tylko wzorzec adaptera?
Charles Graham,
1
Usługa sieciowa jest używana przez serwer proxy, podczas gdy wzorzec adaptera jest używany bardziej do konwersji lub tłumaczenia danych z jednej formy na drugą.
hmcclungiii
1

Mówiąc szczegółowo o implementacji, widzę różnicę między serwerem proxy a dekoratorem, adapterem, fasadą ... We wspólnej implementacji tych wzorów istnieje obiekt docelowy owinięty otaczającym obiektem. Klient używa obiektu otaczającego zamiast obiektu docelowego. Obiekt docelowy faktycznie odgrywa ważną rolę w niektórych metodach zamykania obiektu.

Jednak w przypadku serwera proxy otaczający obiekt może sam odtwarzać niektóre metody, po prostu inicjuje obiekt docelowy, gdy klient wywołuje metody, w których musi brać udział obiekt docelowy. Jest to leniwa inicjalizacja. W przypadku innych wzorów otaczanie obiektu jest praktycznie oparte na obiekcie docelowym. Tak więc obiekt docelowy jest zawsze inicjowany wraz z otaczaniem obiektu w konstruktorach / ustawieniach.

Inną rzeczą jest to, że serwer proxy robi dokładnie to samo, co cel, podczas gdy inne wzorce zwiększają funkcjonalność celu.

bnguyen82
źródło
1

Chciałbym dodać przykłady do odpowiedzi Billa Karwinga (co jest świetne przy okazji). Dodam także kilka kluczowych różnic w implementacji, które moim zdaniem brakuje.

Cytowane części pochodzą z odpowiedzi [ https://stackoverflow.com/a/350471/1984346] (Bill Karwing)

Proxy, dekorator, adapter i mostek są odmianami „zawijania” klasy. Ale ich zastosowania są różne.

  • Proxy może być użyte, gdy chcesz leniwie utworzyć instancję obiektu lub ukryć fakt, że dzwonisz do usługi zdalnej lub kontrolować dostęp do obiektu.

ProxyClass i ObjectClass, które są proxy, powinny implementować ten sam interfejs, więc można je zamieniać

Przykład - kosztowny obiekt 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 { ... }
  • Dekorator jest również nazywany „Smart Proxy”. Jest to używane, gdy chcesz dodać funkcjonalność do obiektu, ale nie przez rozszerzenie typu tego obiektu. To pozwala ci to zrobić w czasie wykonywania.

DecoratorClass powinien (mógł) implementować rozszerzony interfejs ObjectClass. Zatem ObjectClass można zastąpić DecoratorClass, ale nie odwrotnie.

Przykład - dodanie funkcji dodawania

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 { ... }
  • Adapter jest używany, gdy masz interfejs abstrakcyjny i chcesz zmapować ten interfejs na inny obiekt, który ma podobną rolę funkcjonalną, ale inny interfejs.

Różnice w implantacji Proxy, dekorator, adapter

Adapter zapewnia inny interfejs dla swojego tematu. Serwer proxy zapewnia ten sam interfejs. Decorator zapewnia ulepszony interfejs.

  • Bridge jest bardzo podobny do Adaptera, ale nazywamy go Bridge, gdy definiujesz zarówno interfejs abstrakcyjny, jak i podstawową implementację. Oznacza to, że nie dostosowujesz się do jakiegoś starszego kodu lub kodu innej firmy, jesteś projektantem całego kodu, ale musisz mieć możliwość wymiany różnych implementacji.

  • Fasada to interfejs wyższego poziomu (czytaj: prostszy) do podsystemu jednej lub więcej klas. Załóżmy, że masz złożoną koncepcję, która wymaga reprezentacji wielu obiektów. Wprowadzanie zmian w tym zestawie obiektów jest mylące, ponieważ nie zawsze wiesz, który obiekt ma metodę, którą musisz wywołać. Nadszedł czas, aby napisać fasadę, która zapewnia metody wysokiego poziomu dla wszystkich złożonych operacji, jakie można wykonać na zbiorze obiektów. Przykład: Domain Wzór sekcji szkolnej metod, takich jak countStudents(), reportAttendance(), assignSubstituteTeacher()i tak dalej.

Większość informacji w tej odpowiedzi pochodzi z https://sourcemaking.com/design_patterns , które polecam jako doskonałe źródło wzorców projektowych.

nakashu
źródło
0

Wierzę, że kod da jasne pomysły (w celu uzupełnienia innych odpowiedzi). Zobacz poniżej (Skoncentruj typy, które klasa implementuje i pakuje)

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);
                }

            }
        }
    }

}
Abdul Kader Jeelani
źródło
-3

Wzorzec projektowy to nie matematyka, to połączenie sztuki i inżynierii oprogramowania. Nie ma nic takiego jak w przypadku tego wymagania, musisz użyć proxy, mostu itp. Wzory projektowe są tworzone w celu rozwiązania problemów. Jeśli przewidujesz problem z projektem, użyj go. Na podstawie doświadczenia poznasz konkretny problem, którego wzoru użyć. Jeśli jesteś dobry w solidnych zasadach projektowania, zaimplementowałbyś wzór projektowy, nie wiedząc, że jest to wzór. Typowym przykładem są wzorce statergy i fabryczne

Dlatego skoncentruj się bardziej na zasadach solidnego projektowania, zasad czystego kodowania i ttd

Mahantesh
źródło
Zgadzam się, ale to nie odpowiada na pytanie.
Leon