Ваш Creator
класс - фабрика.Давайте назовем это ProductFactory
, чтобы сделать пример более явным.
(я предполагаю, что вы используете 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();
[...]
}
}
}
Назовите это так:
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
Итак, чтобы ответить на ваш вопрос:
Какое это имеет отношение к подклассам?И для чего я должен использовать подклассы?
Что говорит определение фабричного шаблона, так это то, что фабрика определяет общий API для создания экземпляров определенного типа (обычно это интерфейс или абстрактный класс), но реальный тип возвращаемых реализаций (таким образом, ссылка на подкласс) является ответственностью фабрики.В этом примере фабрика возвращает Product
экземпляров, для которых Book
и Computer
являются допустимыми подклассами.
Существуют другие идиомы для фабрики, например, наличие API для фабрики и конкретные реализациифабрика не принимает type
как в моем примере, но они связаны с типом возвращаемых экземпляров, например:
class ProductFactory
{
public:
virtual Product* Make() = 0;
}
class BookProductFactory : public ProductFactory
{
public:
virtual Product* Make()
{
return new Book();
}
}
В этом классе BookProductFactory
всегдавозвращает Book
экземпляров.
ProductFactory* factory = new BookProductFactory();
Product* p1 = factory->Make(); // p1 is a Book
delete p1;
delete factory;
Для ясности, поскольку, похоже, существует некоторая путаница между Abstract Factory
и Factory method
шаблонами проектирования, давайте рассмотрим конкретный пример:
Использование абстрактной фабрики
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;
}
}
Используется так:
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;
Использование фабричной методики
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;
}
}
Это используется следующим образом:
Store* store = new FreeBooksStore();
Gift* gift = store->MakeGift();
// gift has a FreeBook (Book with price 0) and a Computer
delete gift;
delete store;
Когда вы используете дискриминатор type
, как я делал в исходном примере, мы используем parametized factory methods
- метод, который знает, каксоздавать разные виды объектов.Но это может появиться в виде Abstract Factory
или Factory Method
.Краткий трюк: если вы расширяете фабричный класс, вы используете Abstract Factory.Если вы расширяете класс методами создания, то вы используете Factory Methods.