2011-01-22 32 views
33

Od When would you use the Builder Pattern?,Builder Vs Dekorator wzór

Mówi się, że budowniczy jest odpowiedni na przykład pizzy.

Dlaczego nie dekorator? przez traktowanie Sera, Pepperoni, Bacona jako dodatkowych ozdób na bazie pizzy.

Jest to powód, dla którego Sera/Pepperoni należy budować osobno. Nie sądzę, że trzeba je budować osobno, ponieważ mogą być gotowe.

Pls wyjaśnić. Poszukuję również dobrego przykładu wzornika dekoratorów i powodu, dla którego jest on odpowiedni dla tego konkretnego przykładu. Dziękuję Ci.

+0

miałem tę samą myśl, kiedy dowiedział się o tym na przykładzie. Profesor nie mógł mi pomóc, ale tak jest, dziękuję! – Mene

Odpowiedz

36

Z Wikipedii dekorator deseń artykułu:

W programowaniu obiektowym The dekorator wzorzec jest wzorcem projektowania który umożliwia nowe/dodatkowe zachowanie należy dodać do istniejącego obiektu dynamicznie.

Nie ma potrzeby dodawania dodatków do pizzy po jej zakończeniu. Nie jesz połowy pizzy, a potem dodajesz do niej kolejną zalewkę.

Innymi słowy, Wzorzec Builder ułatwia zbudować obiekt, który jest rozszerzalny w niezależnych kierunkach na czas budowy, natomiast Wzorzec Dekorator pozwala dodawać rozszerzenia funkcjonalności do obiektu po czasie budowy. Używanie wzoru dekoratora do konstruowania obiektów jest złe, ponieważ pozostawia obiekt w niespójnym (lub co najmniej niepoprawnym) stanie do momentu, gdy wszystkie wymagane dekoratory są na miejscu - podobnie jak problem JavaBeans dotyczący używania seterów do określania opcjonalnych argumentów konstruktora.

+1

Potter: W rzeczywistości, niektóre dodatki takie jak kitchup, płatki chili będą podawane wraz z Pizza. Czy możemy więc powiedzieć, że stosujemy oba wzory? Pierwszy budowniczy, potem dekorator? – bjskishore123

+0

Potter: +1, moje powyższe założenie wydaje się być poprawne w kwestii dodatków, zaczerpnięte z http://stackoverflow.com/questions/2707401/please-help-me-understand-decorator-pattern-with-real-world- przykład – bjskishore123

+3

@bjs: tak, dekorator i budowniczy mogą być rozsądnie połączone, a twoim przykładem jest jedna możliwość; jednak prowadzi do złożonego projektu i mniej czytelnego kodu. Korzystałbym tylko z Builder + Decorator, gdybym był pewien, że jest to rzeczywiście wymagane przez projekt, a nie tylko przypadek "Pattern Fever" z mojej strony.Zastanów się, czy warto dodać metodę 'addChilli()' do klasy bazowej, zamiast budować pełną wersję 'ChilliDecorator'. (Jak zawsze nie ma poprawnej odpowiedzi). –

20

Mylą dwie bardzo różne rzeczy. GoF klasyfikuje Builder jako wzorzec kreacji, podczas gdy Dekorator jest strukturalny. Są one opisane w następujący sposób (gamma i inni, strona 1)

Konstruktor (97) oddzielenie konstrukcji zespolonej obiektu z reprezentacji tak że ten sam proces budowy można tworzyć różne reprezentacje.

Dekorator (175) Dynamiczne przypisywanie dodatkowych obowiązków do obiektu. Dekoratory stanowią elastyczną alternatywę dla podklasy w celu rozszerzenia funkcjonalności.

Uwaga na nacisk na dekoratora. Jest elastyczną alternatywą dla podklasy. Podklasy są używane do modelowania relacji is-a. Ser nie jest pizzą. Pizza jest skomponowana z wielu składników i zazwyczaj jest modelowana za pomocą kompozycji.

Wzorzec budowniczy ma tu znaczenie, ponieważ istnieje tak duża liczba składników, że powstaje potrzeba ich skonstruowania w znormalizowany sposób.

Aby zrobić prawdziwy przykład dekoratora, niedawno chciałem zarejestrować zapytania wykonane przy użyciu jdbc w mojej aplikacji java. Osiągnąłem to poprzez wdrożenie klasy o nazwie LoggingConnection, która rozszerzyła interfejs połączenia.

public class LoggingConnection implements Connection 
{ 
    public static class LogEntry 
    { 
     public String sql; 
     public int invocationCount; 
     public double avgTime; 
     public double maxTime; 
    } 

    private Connection delegate; 

    private Map<String, LogEntry> log; 

    public LoggingConnection(Connection delegate) 
    { 
     this.delegate = delegate; 
     this.log = new HashMap<String, LogEntry>(); 
    } 

    public Map<String, LogEntry> getLog() 
    { 
     return log; 
    } 

    @Override 
    public void clearWarnings() 
    throws SQLException 
    { 
     delegate.clearWarnings(); 
    } 

    @Override 
    public void close() 
    throws SQLException 
    { 
     delegate.close(); 
    } 

    // forwarding declarations to all other methods declared in the interface 
    ... 
} 

Pozwala mi to przekazać konkretną implementację połączenia i rozszerzyć jego funkcjonalność w czasie wykonywania. Tworzenie podklas może być problematyczne w tym kontekście, ponieważ niekoniecznie wiesz, jaki obiekt połączenia jest faktycznie zwracany. To dlatego, że jest zbudowany na używasz fabrykę DriverManager:

Connection conn = DriverManger.getConnection(dsn); 

Conn obiekt jest w tym przypadku realizacja zawartych w sterowniku, który ja generelly nie znam nazwy. Ideą dekoratora jest to, że nie muszę wiedzieć i że nie jest on związany z konkretną realizacją.

+1

Cóż, "alternatywa" sugeruje, że można również zastosować podklasę. Alternatywą dla podklasy nie jest to, aby ser był podklasą pizzy, ale raczej ma serową podklasę pizzy. Ponieważ pizza z serem to pizza. –

+0

@ Lèse: Ale można sobie wyobrazić, że można zaimplementować dekorator, który dodaje taką samą funkcję "sera" jak podklasa. Jedyną istotną różnicą jest to, że możesz zdecydować się na rozszerzenie w czasie wykonywania. –

+0

+1: Pomocne, dziękuję. – bjskishore123

1

Wzór konstruktora jest specjalnie używany do budowania i dekoratora, aby dodać funkcje specjalne do kompilacji postów. np. W powyższym przykładzie Pizza możemy zdecydować się na użycie jednego z dwóch wzorów opartych na domenie problemu.

Jeśli płatki chilli są niezbędne dla pizzy i podobnie, mamy wiele składników, które można dodać do pizzy, z których kilka podstawowych elementów sprawia, że ​​pizza jest jadalna (znaczący stan), możemy jednak użyć Buildera. Po zbudowaniu pizzy możemy później udekorować ją różnymi dodatkami, takimi jak sos pomidorowy, oliwki itp.

Ponadto prawidłowo stwierdzono, że mogą być używane razem, ale to zwiększy złożoność. Powinniśmy więc mądrze używać wzorców tylko wtedy, gdy jest to potrzebne w domenie problemu, w przeciwnym razie wystarczy prosta konstrukcja.

2

Przejdźmy przez najważniejsze cechy Builder i Dekorator.

Builder: (A kreacyjnych wzór)

  1. zbyt wiele argumentów, aby przejść z programu klienckiego do klasy fabryczne, które mogą być podatne na błędy
  2. Niektóre parametry mogą być opcjonalnie w przeciwieństwie do fabryki, która wymusza wyślij wszystkie parametry
  3. Obiekt jest ciężki, a jego tworzenie jest złożone. na przykład budując różne rodzaje pizzy

Decorator: (A strukturalny)

  1. Dodaj do zachowania obiektu w czasie wykonywania. Dziedziczenie jest kluczem do osiągnięcia tej funkcjonalności, co jest zaletą i wadą tego wzoru.
  2. Poprawia zachowanie interfejsu.
  3. Dekorator może być postrzegany jako zdegenerowany kompozyt tylko z jednym komponentem. Jednak dekorator dodaje dodatkowe obowiązki - nie jest przeznaczony do agregacji obiektów.
  4. Dekorator obsługuje preparatowi rekurencyjnych
  5. Dekorator jest zaprojektowany, aby umożliwić dodanie zadania do obiektów bez sub-classing

Kiedy używać Dekorator:

  1. obowiązki obiekt i Zachowania powinny być dynamicznie dodawane/usuwane
  2. Konkretne implementacje powinny być oddzielone od obowiązków i zachowania
  3. Kiedy sub - classing jest zbyt kosztowne, aby dynamicznie dodawać/usuwać obowiązki

Wracając do zapytania:

Builder ma rację kreacyjnych wzór Pizza. Pizza jest tworzona z początkowo obowiązkowymi składnikami (chleb itp.). Ser, Pepperoni, Bacon są opcjonalnymi składnikami, ale mimo to mogą być częścią pizzy podczas procesu tworzenia.

Dekorator jest przydatny do dodawania dynamicznych obowiązków w czasie wykonywania dla już utworzonego obiektu.

np. :

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt"))); 

Patrz poniżej stanowisk więcej szczegółów:

Keeping builder in separate class (fluent interface)

When to Use the Decorator Pattern?