5

Rozumiem, że jedną z głównych zalet metody fabryki w porównaniu z prostą fabryką jest to, że nie narusza ona zasady Open-Closed SOLID. Oznacza to, że ta pierwsza nie wymaga modyfikacji instrukcji switch, gdy dodawane są nowe typy.Metoda prosta fabryka a metoda fabryczna: Instrukcja przełączania w przypadku klienta fabrycznego

Jest jeden artykuł, w którym mam nadzieję uzyskać wyjaśnienia. Gdybym miał użyć prostego fabrykę, chciałbym mieć fabrykę takiego (uproszczony):

public class ObjectFactory { 
    public static IObject CreateObject(ObjectTypeEnum objectType) { 
     switch (objectType) { 
      case TypeA: 
       return ObjectA; 
       break; 
      case TypeB: 
       return ObjectB; 
       break; 
      case TypeC: 
       return ObjectC; 
       break; 
     } 
    } 
} 

a klient nazwałbym to tak:

IObject myObject = ObjectFactory.CreateObject(objectType); 

Wadą w literaturze jest to, że Obiekt CreateObject będzie musiał zostać zmodyfikowany po dodaniu nowych typów obiektów.

Ale metoda fabryki, to nie możemy być po prostu przesuwając tę ​​zmianę z fabryki do klienta, jak ten (kod klienta):

IObject myObject; 
switch (objectType) { 
      case TypeA: 
       myObject = ObjectAFactory.CreateObject(); 
       break; 
      case TypeB: 
       myObject = ObjectBFactory.CreateObject(); 
       break; 
      case TypeC: 
       myObject = ObjectCFactory.CreateObject(); 
       break; 
} 

W tym przypadku klient będzie musiał zostać zmodyfikowany za każdym razem, gdy zostanie dodany nowy typ, w porównaniu do poprzedniego przypadku konieczna będzie modyfikacja fabryki. Więc jaka jest przewaga jednej nad drugą? Proszę nie oznaczać tego jako duplikatu, przyjrzałem się wielu postom dotyczącym SO na temat fabryk i żadne z nich nie odnosi się do tego konkretnego rozróżnienia.

Czy istnieje lepsze rozwiązanie, które nie narusza zasady Open/Closed po stronie klienta lub fabryki?

Odpowiedz

1

Standardowy wzór projektu Abstract Factory nie pomaga?
kod uproszczony Java:

public interface IFactory { 
    IObject createObject(); 
} 

public class FactoryA implements IFactory { 
    public IObject createObject() { 
     return new ObjectA(); 
    } 
} 

public class FactoryB implements IFactory { 
    public IObject createObject() { 
     return new ObjectB(); 
    } 
} 

Client is configured (injected) with the needed Factory at run-time 
    IFactory myFactory = ... // new FactoryA(); 
... 
IObject myObject = myFactory.createObject(); 
... 

Zobacz także GoF Wzorce projektowe pamięci/Abstract Factory w http://w3sdesign.com.

WARIANT 2
Zamiast używać obiektów typu wyliczanie, zdefiniuj typy obiektów za pomocą polimorfizmu (aby uniknąć instrukcji przełączania). uproszczony kod Java:

public interface IObjectType { 
    int getObjectType(); 
    IObject createObject(); 
} 

public class ObjectTypeA implements IObjectType { 
    ... 
    public IObject createObject() { 
     return new ObjectA(); 
    } 
} 

public class ObjectTypeB implements IObjectType { 
    ... 
    public IObject createObject() { 
     return new ObjectB(); 
    } 
} 

Client determines object type 
IObjectType myObjectType = ... // new ObjectTypeA(); 
... 
IObject myObject = myObjectType.createObject(); 
... 

Mój wniosek:
myślę, że lepszym rozwiązaniem byłoby zaprojektować swoje typy z polimorfizmem zamiast korzystania constans enum. Unikałoby to instrukcji przełączania i nie naruszałoby Zasady Otwartej/Zamkniętej po stronie klienta lub fabryki.

+0

Jest to zasadniczo odmiana mojej drugiej opcji powyżej. Powodem, dla którego to nie działa, jest to, że w moim przypadku "klient" fabryki to tak naprawdę interfejs Web API. Klient Web API ("klient klienta") będzie decydował o tym, jaki jest typ obiektu, więc nie widzę sposobu, aby go wprowadzić bez zmiany typu obiektu, bez względu na to, czy jest to api, które tworzy Pouczający lub w samej fabryce. – mayabelle

+0

Jak klienci określają typ obiektu? – GFranke

+0

Klient przekazuje typ obiektu, który chce, do api. Typ obiektu to wartość wyliczeniowa. – mayabelle