Twoja klasa Creator
jest fabrycznie. Nazwijmy to numerem ProductFactory
, aby przykład był bardziej wyraźny.
(jestem zakładając używasz C++)
class Book : public Product
{
};
class Computer : public Product
{
};
class ProductFactory
{
public:
virtual Product* Make(int type)
{
switch (type)
{
case 0:
return new Book();
case 1:
return new Computer();
[...]
}
}
}
nazwać to tak:
ProductFactory factory = ....;
Product* p1 = factory.Make(0); // p1 is a Book*
Product* p2 = factory.Make(1); // p2 is a Computer*
// remember to delete p1 and p2
Tak więc, aby odpowiedzieć na pytanie:
Co robi mieć do czynienia z podklasami? I do czego mam używać podklas ?
Co oznacza definicja fabrycznego wzorca, to że fabryka definiuje wspólny interfejs API do tworzenia wystąpień określonego typu (zwykle jest to interfejs lub klasa abstrakcyjna), ale rzeczywisty typ zwróconych implementacji (a więc podklasa odniesienie) jest obowiązkiem fabryki. W tym przykładzie fabryka zwraca instancje Product
, dla których Book
i Computer
są poprawnymi podklasami.
Istnieją inne idiomy dla fabryki, jakby API dla fabryki i konkretnych wdrożeń fabryce nie zaakceptować type
jak w moim przykładzie, ale są one w połączeniu z typem przypadkach zwracane, tak :
class ProductFactory
{
public:
virtual Product* Make() = 0;
}
class BookProductFactory : public ProductFactory
{
public:
virtual Product* Make()
{
return new Book();
}
}
W tej klasie BookProductFactory
zawsze zwraca Book
instancji.
ProductFactory* factory = new BookProductFactory();
Product* p1 = factory->Make(); // p1 is a Book
delete p1;
delete factory;
Żeby było jasne, ponieważ nie wydaje się być nieco pomylenia Abstract Factory
i Factory method
wzorców projektowych, zobaczmy konkretny przykład:
Korzystanie Abstract Factory
class ProductFactory {
protected:
virtual Product* MakeBook() = 0;
virtual Product* MakeComputer() = 0;
}
class Store {
public:
Gift* MakeGift(ProductFactory* factory) {
Product* p1 = factory->MakeBook();
Product* p2 = factory->MakeComputer();
return new Gift(p1, p2);
}
}
class StoreProductFactory : public ProductFactory {
protected:
virtual Product* MakeBook() { return new Book(); }
virtual Product* MakeComputer() { return new Computer(); }
}
class FreeBooksStoreProductFactory : public StoreProductFactory {
protected:
virtual Product* MakeBook() {
Book* b = new FreeBook(); // a FreeBook is a Book with price 0
return b;
}
}
Jest to używane w następujący sposób:
Store store;
ProductFactory* factory = new FreeBooksStoreProductFactory();
Gift* gift = factory->MakeGift(factory);
// gift has a FreeBook (Book with price 0) and a Computer
delete gift;
delete factory;
Użycie metody fabryki
class Store {
public:
Gift* MakeGift() {
Product* p1 = MakeBook();
Product* p2 = MakeComputer();
return new Gift(p1, p2);
}
protected:
virtual Product* MakeBook() {
return new Book();
}
virtual Product* MakeComputer() {
return new Computer();
}
}
class FreeBooksStore : public Store {
protected:
virtual Product* MakeBook() {
Book* b = new FreeBook(); // a FreeBook is a Book with price 0
return b;
}
}
który jest używany tak:
Store* store = new FreeBooksStore();
Gift* gift = store->MakeGift();
// gift has a FreeBook (Book with price 0) and a Computer
delete gift;
delete store;
Podczas korzystania z type
dyskryminator tak jak ja w oryginalnym przykład używamy parametized factory methods
- metoda, która wie, jak tworzyć różne rodzaje obiektów. Ale może pojawić się wzór Abstract Factory
lub Factory Method
. Krótka sztuczka: jeśli rozszerzasz klasę fabryczną, używasz Abstract Factory. Jeśli rozszerzasz klasę o metody tworzenia, używasz metod fabrycznych.
tak, w twoim kodzie, ProductFactory jest Abstract Factory, a make jest metodą Factory, prawda? – Alcott
Różnica między 'Abstract Factory' i' Factory Method' będzie kwestią samą w sobie :) Krótko mówiąc, kiedy używasz dyskryminatora typu, tak jak to zrobiłem w przykładzie, używamy "sparametryzowanych metod fabrycznych" - metody, która wie, jak tworzyć różne rodzaje obiektów. Ale może pojawić się w abstrakcyjnej fabryce lub metodzie metody Factory. Krótka sztuczka: jeśli rozszerzasz klasę fabryczną, używasz 'Abstract Factory'. Jeśli rozszerzysz klasę o _factory methods_, użyjesz 'Factory Methods'. Jeśli różnica jest nadal niejasna, stanowią inne pytanie na SO. –
Aby było jasne. Moja odpowiedź nie używa wzorca projektu "Factory method", lecz wzorca projektu "Abstract Factory". –