15

Robię dogłębne badanie wzorców projektowych i natknąłem się na prototyp, którego tak naprawdę nie studiowałem wcześniej. Przeszukałem internet i kilka książek, a nie ma naprawdę dobrego przykładu prototypu, który mógłby znaleźć nie tylko klon. Czy wzór prototypu jest w zasadzie językową cechą java i C# jako klonem?Czy prototypowy wzór naprawdę jest po prostu sklonowany?

+3

Wzory są niezależne od języka abstrakcje, klon to specyficzny idiom języka. Byłoby słuszne stwierdzenie, że wzorzec prototypu jest uogólnieniem idiomu klonu, lub że klon jest specyficznym językowo idiomem prototypu, ale byłoby błędem powiązać go ściśle z idiomem jednego języka. –

Odpowiedz

18

Wzór prototypowy to znacznie więcej niż klon. Klonowa semantyka jest szersza, co oznacza, że ​​pola skalarów/wartości jednej instancji obiektu są duplikowane w nowej instancji, tak, że mają stan równoważny, ale zajmują różne lokalizacje w pamięci. Klon może być używany do obsługi wielu różnych potrzeb.

Prototypowy wzór zawiera Klon w szczególności do rozwiązania większego problemu oddzielenia konstrukcji obiektu od użycia obiektu. Prototypowa semantyka stwierdza, że ​​jedyną (lub przynajmniej obsługiwaną/preferowaną) metodą konstruowania nowego obiektu wymaganego zachowania jest Klonowanie określonej instancji, znanej jako prototypowa instancja. Te prototypowe instancje mogą żyć w fabryce prototypów, która jest zaimplementowana do tworzenia nowych instancji przez wywołanie Clone w prototypowych instancjach. Prototypowe instancje można zainicjować za pomocą wtrysku zależności. Kod wstrzykiwania jest jedynym kodem, który musi wiedzieć, jak zbudować prototypowe instancje, a to faktycznie staje się rzeczywistym kodem fabrycznym.

Mam nadzieję, że po klasa przykład fabryka wyjaśnia sedno wzoru:

public class PrototypeWidgetFactory : IWidgetFactory 
{ 
    public PrototypeWidgetFactory(PrototypeWidget scenarioA, PrototypeWidget scenarioB, PrototypeWidget scenarioC) 
    { 
    _scenarioA = scenarioA; 
    _scenarioB = scenarioB; 
    _scenarioC = scenarioC; 
    } 

    public Widget GetForScenarioA() { return _scenarioA.Clone(); } 
    public Widget GetForScenarioB() { return _scenarioB.Clone(); } 
    public Widget GetForScenarioC() { return _scenarioC.Clone(); } 

    private PrototypeWidgetFactory _scenarioA; 
    private PrototypeWidgetFactory _scenarioB; 
    private PrototypeWidgetFactory _scenarioC; 
} 

Instancja tej fabryce mogą być przekazywane gdziekolwiek IWidgetFactory jest potrzebne. Zaletą jest to, że nie potrzebujesz wielu różnych klas fabrycznych dla każdego zachowania. W rzeczywistości, w przypadku niektórych typów zachowań, nie potrzebujesz nawet kilku różnych klas, jeśli po prostu wstrzykniesz instancje tego samego typu, które są inicjowane inaczej do fabryki prototypów. W tym przypadku przewaga jest jeszcze większa, ponieważ API nie nadąża za grupą małych klas, które niewiele robią.

Wadą jest to, że kod wstrzykiwania musi wiedzieć, jak konstruować prototypy. Jest to kruche, jeśli istnieje dużo złożonej logiki związanej z konstruowaniem prototypów.

(Uwaga: wzorzec prototypowy nie wymaga, aby wszystkie metody na fabrykach prototypów zwracały ten sam typ, po prostu zwróciłem tylko przykład Widgety, ponieważ to pokazuje większą korzyść z używania prototypów do konstruowania obiektów dla konkretnych zachowań, gdy obiekty są jednego rodzaju, ale zainicjowany inaczej).

public class PrototypeDomainFactory : IDomainFactory 
{ 
    public PrototypeDomainFactory(PrototypePerson personPrototype, PrototypeCompany companyPrototype, PrototypeWidget widgetPrototype) 
    { 
    _personPrototype = personPrototype; 
    _companyPrototype = companyPrototype; 
    _widgetPrototype = widgetPrototype; 
    } 

    public Person GetPerson() { return _personPrototype.Clone(); } 
    public Company GetCompany() { return _companyPrototype.Clone(); } 
    public Widget GetWidget() { return _widgetPrototype.Clone(); } 

    private PrototypePerson _personPrototype; 
    private PrototypeCompany _companyPrototype; 
    private PrototypeWidget _widgetPrototype; 
} 
0

Klon() jest zdecydowanie częścią tego. Myślę, że wzorzec mówi także o sposobach zbierania przedmiotów, iteracji przez nie i znalezienia odpowiedniego do klonowania. Musisz także ustawić obiekty na początek.

4

Sorta. Clone() robi dużo tego, co chcesz dla celów Prototype, ale jeśli chcesz, możesz pójść o wiele dalej. Zobacz Steve Yegge's deep (and lengthy!) explanation lub zapoznaj się z modelem obiektu JavaScript.

+1

To nie jest prototyp - (choć jest to z pewnością powiązane) - nazywa go Wzorem Właściwości. W JavaScript słowo "prototyp" jest używane do opisania części tego, a klonowanie jest zdecydowanie zaangażowane, ale wciąż uważam je za różne rzeczy. Prototyp w GoF nie mówi o idei właściwości dynamicznych. –

+0

To słuszne.Zawsze myślałem o prototypie jako o właściwościach dynamicznych i iterowalności, tylko dlatego, że jeśli tak nie jest * jest * w zasadzie Clone() i wydaje się, że jest kiepski. –

+0

Wow, dzięki za zamieszczenie tego wpisu w blogu. Bardzo dobrze czytać. Wiele się nauczyłem, czytając to. Zgadzam się, że nie jest to prototypowy wzór opisany w książce GoF. –