C++设计模式——Factory Method工厂方法模式

一,工厂方法模式的定义
工厂方法模式是一种创建型设计模式,它提供了一种创建对象的方法,而无需指定具体的类,也不需要直接指定对象的类型。
工厂方法模式抽象了对象的创建过程,使得客户端只需要通过指定具体的参数,而无需关心对象的创建细节。
工厂方法模式将创建对象的逻辑封装在一个类(工厂类)中,它提供了一种通过调用工厂类的方法来创建对象的方式,而无需直接使用对象的构造函数,外部客户端通过调用工厂类的方法来获取所需的对象。
由于工厂方法模式将创建对象的逻辑封装在了一个工厂类中,这种设计可以让对象的创建与使用的解耦,提高了代码的灵活性和可维护性。

工厂方法模式在现实生活中的抽象实例:
餐厅点餐:餐厅根据顾客的下单来订做相应的食物。
汽车制造:汽车厂商通过固定的工厂流水线生产不同型号和外观的汽车。
服装定制:顾客在服装店通过选择设计、尺寸和面料等要素来定制自己的服装。

二,工厂方法模式的结构

工厂方法模式主要包含以下组件:
1.抽象工厂(Factory):
定义创建产品的接口,包含创建产品对象的抽象方法。

2.具体工厂(Concrete Factory):
是抽象工厂的具体实现,负责创建具体的产品对象,具体工厂根据调用场景来决定实例化哪一个具体产品类,并返回该产品的实例。

3.抽象产品(Product):
定义了产品的主要特性和功能。

4.具体产品(Concrete Product):
是抽象产品的具体实现。

组件之间的工作步骤如下:
1.客户端通过调用具体工厂的方法来创建产品。客户端并不知道具体的产品类,只知道抽象接口。
2.具体工厂接收到客户端的请求后,根据一定的条件来决定实例化哪一类具体产品,并调用具体产品类的构造函数。
3.具体产品类实例化后,将产品返回给客户端使用。

对应UML类图:

三,工厂方法模式代码样例

include

class Product {
public:
virtual void use() = 0;
};

class ConcreteProductA: public Product{
public:
void use() {
std::cout << “Using ConcreteProductA” << std::endl;
}
};

class ConcreteProductB: public Product{
public:
void use() {
std::cout << “Using ConcreteProductB” << std::endl;
}
};

class Factory{
public:
virtual Product* createProduct() = 0;
};

class ConcreteFactoryA: public Factory{
public:
Product* createProduct() {
return new ConcreteProductA();
}
};

class ConcreteFactoryB: public Factory{
public:
Product* createProduct() {
return new ConcreteProductB();
}
};

int main() {
Factory* factoryA = new ConcreteFactoryA();
Product* productA = factoryA->createProduct();
productA->use();

Factory* factoryB = new ConcreteFactoryB();
Product* productB = factoryB->createProduct();
productB->use();

delete factoryA;
delete productA;
delete factoryB;
delete productB;
return 0;

}
运行结果:
Using ConcreteProductA
Using ConcreteProductB
四,工厂方法模式的优缺点

工厂方法模式的优点:
将对象的创建与使用分离,客户端无需知道具体的产品类,也不需要知道具体产品的实现细节。
降低了客户端和具体产品类之间的耦合度。
如果需要更换具体产品类,只需要修改工厂类的实现即可,而不需要修改客户端的代码。
可以在工厂类中实现对象的生命周期管理和对象池等功能。
可以在工厂类中实现对象的复用,如果多个客户端需要同一个对象,可以通过工厂类实现对象的共享,避免重复创建对象。

工厂方法模式的缺点:
引入工厂类之后,系统会多出一个类,增加了代码的复杂度和理解难度。
需要额外的工厂类来创建对象,会带来一定的性能开销。
只适用于创建具有相同接口或基类的对象,如果需要创建具有不同接口的对象,该模式不适用。

五,代码实战

Demo1:

include

class Product {
public:
virtual ~Product() {}
virtual void operation() = 0;
};

class Factory {
public:
virtual ~Factory() {}
virtual Product* createProduct() = 0;
};

class ProductA : public Product {
public:
void operation() override {
std::cout << “Performing Operation A…” << std::endl;
}
};

class ProductB : public Product {
public:
void operation() override {
std::cout << “Performing Operation B…” << std::endl;
}
};

class FactoryA : public Factory {
public:
Product* createProduct() override { return new ProductA(); }
};

class FactoryB : public Factory {
public:
Product* createProduct() override { return new ProductB(); }
};

int main() {
Factory* factoryA = new FactoryA();
Product* productA = factoryA->createProduct();
productA->operation();
Factory* factoryB = new FactoryB();
Product* productB = factoryB->createProduct();
productB->operation();
return 0;
}
运行结果:
Performing Operation A…
Performing Operation B…

Demo2:

include

include

include

using namespace std;

//Abstract Product
class Page
{
public:
virtual string GetPageName(void) = 0;
};

//Concrete Product
class SkillsPage : public Page
{
public:
string GetPageName(void)
{
return “SkillsPage”;
}
};

//Concrete Product
class EducationPage : public Page
{
public:
string GetPageName(void)
{
return “EducationPage”;
}
};

//Concrete Product
class ExperiencePage : public Page
{
public:
string GetPageName(void)
{
return “ExperiencePage”;
}
};

//Concrete Product
class IntroductionPage : public Page
{
public:
string GetPageName(void)
{
return “IntroductionPage”;
}
};

//Concrete Product
class ResultsPage : public Page
{
public:
string GetPageName(void)
{
return “ResultsPage”;
}
};

//Concrete Product
class ConclusionPage : public Page
{
public:
string GetPageName(void)
{
return “ConclusionPage”;
}
};

//Concrete Product
class SummaryPage : public Page
{
public:
string GetPageName(void)
{
return “SummaryPage”;
}
};

//Concrete Product
class BibliographyPage : public Page
{
public:
string GetPageName(void)
{
return “BibliographyPage”;
}
};

//Abstract Factory
class Document
{
public:
Document()
{
}
void AddPages(Page* page)
{
pages_.push_back(page);
}
const list>& GetPages(void) { return pages_; } //Factory Method virtual void CreatePages(void) = 0; private: list> pages_;
};

//Concrete Factory
class Resume : public Document
{
public:
Resume()
{
CreatePages();
}
void CreatePages(void)
{
AddPages(new SkillsPage());
AddPages(new EducationPage());
AddPages(new ExperiencePage());
}
};

//Concrete Factory
class Report : public Document
{
public:
Report()
{
CreatePages();
}
void CreatePages(void)
{
AddPages(new SummaryPage());
AddPages(new IntroductionPage());
AddPages(new ResultsPage());
AddPages(new ConclusionPage());
AddPages(new BibliographyPage());
}
};

int main()
{
Document* doc1 = new Resume();
Document* doc2 = new Report();
//Get and print the pages of the first document
list>& doc1Pages = const_cast>&> (doc1->GetPages());
cout << “\nResume Pages ————-” << endl; for (list>::iterator it = doc1Pages.begin(); it != doc1Pages.end(); it++) { cout << “\t” << (it)->GetPageName() << endl; } //Get and print the pages of the second document list>& doc2Pages = const_cast>&> (doc2->GetPages());
cout << “\nReport Pages ————-” << endl; for (list>::iterator it = doc2Pages.begin(); it != doc2Pages.end(); it++) { cout << “\t” << (it)->GetPageName() << endl;
}
return 0;
}
运行结果:

Resume Pages ————-
SkillsPage
EducationPage
ExperiencePage

Report Pages ————-
SummaryPage
IntroductionPage
ResultsPage
ConclusionPage
BibliographyPage

六,参考阅读
https://www.codeproject.com/Articles/570183/Factory-Method-Pattern
https://artofcoding.dev/design-patterns-factory-and-factory-method
https://sourcemaking.com/design_patterns/factory_method
https://www.geeksforgeeks.org/factory-method-for-designing-pattern/
https://advancedcppwithexamples.blogspot.com/2010/08/c-example-for-factory-method-design.html

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/423152.html

联系我们
联系我们
分享本页
返回顶部