Ваш 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
. Небольшой трюк: если вы расширяете фабричный класс, вы используете абстрактную фабрику. Если вы расширяете класс методами создания, вы используете фабричные методы.
person
Jorge Ferreira
schedule
19.09.2011