Знакомство с фабричным шаблоном
Давайте сначала посмотрим на введение фабричного шаблона
Этот тип шаблона проектирования представляет собой порождающий шаблон, обеспечивающий оптимальный способ создания объектов. В фабричном шаблоне мы не раскрываем логику создания клиенту при создании объектов и используем общий интерфейс для указания на вновь созданные объекты.
Проще говоря, C++ используетсяполиморфизмхарактеристики, будетнаследоватькласс отношений, черезСоздание фабричного классаСоответствующий объект подкласса (производного класса). В случае сложных проектов можно упростить создание объектов подкласса.
Фабричный шаблон может быть реализован отдельноПростой заводской шаблон,Шаблон фабричного метода,Абстрактный заводской узор, каждая реализация имеет преимущества и недостатки.
В последнее время спекуляция обувью очень горяча, поэтому в виде обувных фабрик мы проанализируем каждый метод реализации один за другим.
Простой заводской шаблон
Конкретная ситуация:
- Обувные фабрики могут заказать производство обуви под брендами Nike, Adidas и Li Ning. Какие туфли горячие, начальник выдаст какие, в зависимости от ситуации.
UML-диаграмма:
простая фабричная выкройкаСтруктура и состав:
-
Заводской класс(
ShoesFactory
): основной класс фабричного шаблона, который определяет интерфейс для создания указанного объекта конкретного экземпляра. -
абстрактный класс продукта(
Shoes
): унаследованный родительский класс или реализованный интерфейс определенного класса продукта. -
конкретная категория продукта(
NiKeShoes\AdidasShoes\LiNingShoes
): Объект, созданный фабричным классом, является этим конкретным экземпляром продукта.
простая фабричная выкройкаФункции:
- Фабричный класс инкапсулирует функции, которые создают конкретные объекты продукта.
простая фабричная выкройкадефект:
- Масштабируемость очень плохая, при добавлении новых продуктов нужно модифицировать фабричный класс.
простая фабричная выкройкакод:
-
Shoes
— абстрактный класс (базовый класс) обуви, а функция интерфейса —Show()
, который используется для показа рекламы обуви. -
NiKeShoes
,AdidasShoes
,LiNingShoes
Категория конкретной обуви, а именно обувь Nike, Adidas и Li Ning, унаследованная отShoes
абстрактный класс.
// 鞋子抽象类
class Shoes
{
public:
virtual ~Shoes() {}
virtual void Show() = 0;
};
// 耐克鞋子
class NiKeShoes : public Shoes
{
public:
void Show()
{
std::cout << "我是耐克球鞋,我的广告语:Just do it" << std::endl;
}
};
// 阿迪达斯鞋子
class AdidasShoes : public Shoes
{
public:
void Show()
{
std::cout << "我是阿迪达斯球鞋,我的广告语:Impossible is nothing" << std::endl;
}
};
// 李宁鞋子
class LiNingShoes : public Shoes
{
public:
void Show()
{
std::cout << "我是李宁球鞋,我的广告语:Everything is possible" << std::endl;
}
};
-
ShoesFactory
Для фабричного класса реализуется создание соответствующего объекта обувного продукта в соответствии с типом обуви.CreateShoes(SHOES_TYPE type)
функция.
enum SHOES_TYPE
{
NIKE,
LINING,
ADIDAS
};
// 总鞋厂
class ShoesFactory
{
public:
// 根据鞋子类型创建对应的鞋子对象
Shoes *CreateShoes(SHOES_TYPE type)
{
switch (type)
{
case NIKE:
return new NiKeShoes();
break;
case LINING:
return new LiNingShoes();
break;
case ADIDAS:
return new AdidasShoes();
break;
default:
return NULL;
break;
}
}
};
-
main
Функция сначала строит объект фабрики, а затем создает конкретный объект обувного продукта указанного типа.После создания конкретного объекта обувного продукта реклама может быть напечатана напрямую. посколькуnew
Объект создается в пути, и когда он израсходуется, его нужно пройтиdelete
Освободите ресурсы!
int main()
{
// 构造工厂对象
ShoesFactory shoesFactory;
// 从鞋工厂对象创建阿迪达斯鞋对象
Shoes *pNikeShoes = shoesFactory.CreateShoes(NIKE);
if (pNikeShoes != NULL)
{
// 耐克球鞋广告喊起
pNikeShoes->Show();
// 释放资源
delete pNikeShoes;
pNikeShoes = NULL;
}
// 从鞋工厂对象创建阿迪达斯鞋对象
Shoes *pLiNingShoes = shoesFactory.CreateShoes(LINING);
if (pLiNingShoes != NULL)
{
// 李宁球鞋广告喊起
pLiNingShoes->Show();
// 释放资源
delete pLiNingShoes;
pLiNingShoes = NULL;
}
// 从鞋工厂对象创建阿迪达斯鞋对象
Shoes *pAdidasShoes = shoesFactory.CreateShoes(ADIDAS);
if (pAdidasShoes != NULL)
{
// 阿迪达斯球鞋广告喊起
pAdidasShoes->Show();
// 释放资源
delete pAdidasShoes;
pAdidasShoes = NULL;
}
return 0;
}
- Выходной результат:
[root@lincoding factory]# ./simpleFactory
我是耐克球鞋,我的广告语:Just do it
我是阿迪达斯球鞋,我的广告语:Impossible is nothing
我是李宁球鞋,我的广告语:Everything is possible
Шаблон фабричного метода
Конкретная ситуация:
- Сейчас все виды обуви очень популярны, поэтому для массового производства каждого вида обуви необходимо наладить независимые производственные линии для разных марок обуви, тогда каждая производственная линия может производить обувь только одного типа марки .
UML-диаграмма:
шаблон фабричного методаСтруктура и состав:
-
абстрактный фабричный классфабрика(
ShoesFactory
): основной класс шаблона фабричного метода, предоставляющий интерфейс для создания определенного продукта, который реализуется конкретным фабричным классом. -
определенный заводской класс(
NiKeProducer\AdidasProducer\LiNingProducer
): унаследован от абстрактной фабрики для реализации метода создания соответствующих конкретных объектов продукта. -
абстрактный класс продукта(
Shoes
): это родительский класс (базовый класс), который наследует конкретный продукт. -
конкретная категория продукта(
NiKeShoes\AdidasShoes\LiNingShoes
): Объект, созданный конкретной фабрикой, является этим классом.
шаблон фабричного методаФункции:
- Шаблон фабричного метода абстрагирует фабричный класс, предоставляет интерфейс для создания конкретных продуктов и предоставляет его реализацию подклассам.
- Применение шаблона фабричного метода заключается не только в инкапсуляции создания конкретных объектов продукта, но и в размещении создания конкретных объектов продукта в конкретной реализации класса фабрики.
шаблон фабричного методадефект:
- Каждый раз, когда добавляется новый продукт, необходимо добавить определенный заводской класс соответствующего продукта. По сравнению с простым фабричным шаблоном, фабричный метод требует большего количества определений классов.
- На производственной линии может быть только один продукт.
Код шаблона фабричного метода:
-
ShoesFactory
Абстрактный класс фабрики, предоставляющий чисто виртуальные функции для создания конкретных обувных изделий. -
NiKeProducer
,AdidasProducer
,LiNingProducer
Конкретный класс фабрики наследует непрерывный класс фабрики и реализует создание соответствующего конкретного объекта обувного продукта.
// 总鞋厂
class ShoesFactory
{
public:
virtual Shoes *CreateShoes() = 0;
virtual ~ShoesFactory() {}
};
// 耐克生产者/生产链
class NiKeProducer : public ShoesFactory
{
public:
Shoes *CreateShoes()
{
return new NiKeShoes();
}
};
// 阿迪达斯生产者/生产链
class AdidasProducer : public ShoesFactory
{
public:
Shoes *CreateShoes()
{
return new AdidasShoes();
}
};
// 李宁生产者/生产链
class LiNingProducer : public ShoesFactory
{
public:
Shoes *CreateShoes()
{
return new LiNingShoes();
}
};
-
main
Функция строит каждый тип производственной линии для каждого типа обуви, а затем каждая производственная линия производит соответствующую обувь. Следует отметить, что определенные фабричные объекты и конкретные объекты продукта должны пройтиdelete
Освободите ресурсы.
int main()
{
// ================ 生产耐克流程 ==================== //
// 鞋厂开设耐克生产线
ShoesFactory *niKeProducer = new NiKeProducer();
// 耐克生产线产出球鞋
Shoes *nikeShoes = niKeProducer->CreateShoes();
// 耐克球鞋广告喊起
nikeShoes->Show();
// 释放资源
delete nikeShoes;
delete niKeProducer;
// ================ 生产阿迪达斯流程 ==================== //
// 鞋厂开设阿迪达斯生产者
ShoesFactory *adidasProducer = new AdidasProducer();
// 阿迪达斯生产线产出球鞋
Shoes *adidasShoes = adidasProducer->CreateShoes();
// 阿迪达斯球鞋广喊起
adidasShoes->Show();
// 释放资源
delete adidasShoes;
delete adidasProducer;
return 0;
}
- Выходной результат:
[root@lincoding factory]# ./methodFactory
我是耐克球鞋,我的广告语:Just do it
我是阿迪达斯球鞋,我的广告语:Impossible is nothing
Абстрактный заводской узор
Конкретная ситуация:
- В целях расширения бизнеса обувная фабрика производит не только обувь, но и одежду спортивных марок.
UML-диаграмма:
Структурный состав абстрактного фабричного шаблона (такой же, как и фабричный метод):
-
абстрактный фабричный классфабрика(
ShoesFactory
): основной класс шаблона фабричного метода, предоставляющий интерфейс для создания определенного продукта, который реализуется конкретным фабричным классом. -
определенный заводской класс(
NiKeProducer
): унаследован от абстрактной фабрики для реализации метода создания соответствующих конкретных объектов продукта. -
абстрактный класс продукта(
Shoes\Clothe
): это родительский класс (базовый класс), который наследует конкретный продукт. -
конкретная категория продукта(
NiKeShoes\NiKeClothe
): Объект, созданный конкретной фабрикой, является этим классом.
Особенности абстрактного фабричного узора:
- Предоставляет интерфейс для создания объектов продукта в нескольких семействах продуктов. Если вы создаете фабрику Nike, вы можете создавать обувь, одежду, брюки и т. д. Nike.
Недостатки абстрактного фабричного шаблона:
- Как и в случае с фабричным методом, при добавлении нового продукта вам необходимо добавить определенный фабричный класс для соответствующего продукта.
Абстрактное касание фабрики — это код:
-
Clothe
иShoes
, которые являются абстрактными классами товаров для одежды и обуви соответственно. -
NiKeClothe
иNiKeShoes
, которые являются определенными категориями продуктов Nike и одежды Nike соответственно.
// 基类 衣服
class Clothe
{
public:
virtual void Show() = 0;
virtual ~Clothe() {}
};
// 耐克衣服
class NiKeClothe : public Clothe
{
public:
void Show()
{
std::cout << "我是耐克衣服,时尚我最在行!" << std::endl;
}
};
// 基类 鞋子
class Shoes
{
public:
virtual void Show() = 0;
virtual ~Shoes() {}
};
// 耐克鞋子
class NiKeShoes : public Shoes
{
public:
void Show()
{
std::cout << "我是耐克球鞋,让你酷起来!" << std::endl;
}
};
-
Factory
Для абстрактной фабрики предусмотрено создание обувиCreateShoes()
и одеждаCreateClothe()
интерфейс объекта. -
NiKeProducer
Для конкретных фабрик реализован способ создания обуви Nike и одежды Nike.
// 总厂
class Factory
{
public:
virtual Shoes *CreateShoes() = 0;
virtual Clothe *CreateClothe() = 0;
virtual ~Factory() {}
};
// 耐克生产者/生产链
class NiKeProducer : public Factory
{
public:
Shoes *CreateShoes()
{
return new NiKeShoes();
}
Clothe *CreateClothe()
{
return new NiKeClothe();
}
};
-
main
Функция, создайте объект фабрики Nike, а затем создайте объекты одежды и обуви семейства продуктов Nike с помощью объекта фабрики Nike. Точно так же ресурсы необходимо освобождать вручную, когда объекты больше не используются.
int main()
{
// ================ 生产耐克流程 ==================== //
// 鞋厂开设耐克生产线
Factory *niKeProducer = new NiKeProducer();
// 耐克生产线产出球鞋
Shoes *nikeShoes = niKeProducer->CreateShoes();
// 耐克生产线产出衣服
Clothe *nikeClothe = niKeProducer->CreateClothe();
// 耐克球鞋广告喊起
nikeShoes->Show();
// 耐克衣服广告喊起
nikeClothe->Show();
// 释放资源
delete nikeShoes;
delete nikeClothe;
delete niKeProducer;
return 0;
}
- Выходной результат:
[root@lincoding factory]# ./abstractFactory
我是耐克球鞋,让你酷起来!
我是耐克衣服,时尚我最在行!
Суммировать
Вышеуказанные три заводские модели имеют определенные дефекты при добавлении новых продуктов.
- Простой фабричный шаблон требует изменения фабричного класса, что нарушает закон открытия-закрытия.
- Как в режиме фабрики, так и в режиме абстрактной фабрики необходимо добавить определенный класс фабрики для соответствующего продукта, что увеличит объем написанного кода.
Так как же можно добавлять новые продукты, не изменяя фабричный класс или добавляя определенный фабричный класс?
Автор увидел класс фабрики с очень сильной инкапсуляцией в реальном проекте. При расширении новых продуктов нет необходимости изменять класс фабрики или добавлять определенный класс фабрики. Для получения подробной информации вы можете перейти кC++ объясняет шаблон фабрики простыми словами (дополнительно)читать.