1.简单工厂思想
简单工厂模式不属于23种设计模式之⼀,更多的是⼀种编程习惯。它的核心思想是将产品的创建过程封装在⼀个⼯⼚类中,把创建对象的流程集中在这个⼯⼚类⾥⾯。卡码网将其结构描述为下图所示的情况:
简单⼯⼚模式包括三个主要⻆⾊,⼯⼚类、抽象产品类、具体产品类。它们的职责如下:
- ⼯⼚类:负责创建产品,根据传递的不同参数创建不同的产品示例。
- 抽象产品类:由工厂类提供的接口,⽐如上图中的 Shape 接⼝,描述产品的通⽤⾏为。
- 具体产品类:实现抽象产品接⼝或继承抽象产品类,⽐如上⾯的 Circle 类和 Square 类,具体产品通过简单⼯⼚类的 if-else 逻辑来实例化。
简单工厂的优点是简化了客户端的操作,客户端可以调用工厂方法来获取具体产品,而无需直接与具体产品类交互,降低了耦合,但是有一个很大的问题就是不够灵活,如果需要添加新的产品,就需要修改工厂类的代码。
2.什么是工厂模式?
简单工厂的思想中只有一个工厂类,用于创建所有的产品,如果需要添加新的产品,就需要修改工厂类的代码。而工厂模式引入了抽象工厂和具体工厂的概念,每个具体工厂只负责创建一个具体产品,添加新产品时只需要添加新的工厂类,支持扩展,复合开闭原则。
工厂方法模式分为以下几个角色:
- 抽象工厂:一个接口,包含一个抽象的工厂方法,该方法用于创建产品对象。
- 具体工厂:实现抽象工厂接口,创建具体的产品。
- 抽象产品类:定义产品的接口。
- 具体产品类:实现抽象产品接口,是工厂创建的对象。
工厂模式的示意图如下图所示,实际的生产系统所管理的是对应的工厂,工厂负责产品的生产。当有具体需求传入时,生产提供根据需求创建对应的工厂,这些工厂去完成需求产品的生产。在有新的产品时,只需要扩展一下产品的内容及其对应的工厂即可,原来的代码无需更改,只需要往里面添加新的模块即可,非常灵活。
3.C++工厂模式
【设计模式专题之工厂方法模式】2.积木工厂 (kamacoder.com)https://kamacoder.com/problempage.php?pid=1076
题目描述:
小明家有两个工厂,一个用于生产圆形积木,一个用于生产方形积木,请你帮他设计一个积木工厂系统,记录积木生产的信息。
输入描述
输入的第一行是一个整数 N(1 ≤ N ≤ 100),表示生产的次数。
接下来的 N 行,每行输入一个字符串和一个整数,字符串表示积木的类型。积木类型分为 "Circle" 和 "Square" 两种。整数表示该积木生产的数量
输出描述
对于每个积木,输出一行字符串表示该积木的信息。
输入示例
3
Circle 1
Square 2
Circle 1
输出示例
Circle Block
Square Block
Square Block
Circle Block
代码实现:
先实现抽象产品类和具体产品类:
//抽象积木产品类,定义生产具体积木的接口produce()
class Block{
public:
//写成纯虚函数,一方面将该类变成抽象类,另一方面方便具体产品类实现多态
virtual void produce() = 0;
};
//具体圆形积木产品类
class CircleBlock: public Block{
public:
//重写父类虚函数,使用override关键字编译器会检查重写是否正确,不是非要加
void produce() override {
cout<<"Circle Block"<<endl;
}
};
//具体方形积木产品类
class SquareBlock: public Block{
public:
//重写父类虚函数
void produce() override
{
cout<<"Square Block"<<endl;
}
};
再实现抽象工厂类和具体工厂类,其中具体工厂类要调用具体产品的生产函数,所以工厂类写在了产品类的后面:
//抽象工厂类,提供一个抽象的接口用于创建对象。具体哪种对象还得用多态实现
class BlockFactory{
public:
//抽象的接口。 使用积木的基类指针作为返回值,其可以接收圆形或方形的积木对象(C++多态允许)
virtual Block* createBlock() = 0;
};
//具体圆形积木工厂类
class CircleBlockFactory:public BlockFactory{
public:
//重写接口函数
Block* createBlock() override
{
return new CircleBlock(); //堆区开辟内存存放积木对象
}
};
//具体方形积木工厂类
class SquareBlockFactory:public BlockFactory{
public:
//重写接口函数
Block* createBlock() override
{
return new SquareBlock(); //堆区开辟内存存放积木对象
}
};
建立积木工厂系统。该系统根据输入要求去建立相对应的工厂,让该工厂去生产具体产品:
//建立积木工厂系统
class BlockManageSystem{
private:
//使用Block*动态数组来记录积木信息
vector<Block *> blocks;
public:
//根据输入,建立积木生产函数。根据具体产品类型调用相对应的产品工厂
void produceBlocks(BlockFactory* factory, int num)
{
for(int i=0; i<num; i++)
{
Block* block = factory->createBlock();
this->blocks.push_back(block);
block->produce();
}
}
//由于具体积木存放在堆区,所以要使用delete进行内存释放
~BlockManageSystem(){
for(Block* block : blocks)
{
delete block;
}
}
//获取所有积木。第一个const修饰返回的引用,即使得到积木,也不能对积木进行修改。
//第二个const修饰this指针,保证this指针不能对积木进行修改
const vector<Block*> & getBlocks()const{
return blocks;
}
};
总体代码:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
//按照工厂模式的组成,依次实现抽象产品类、具体产品类、抽象工厂类、具体工厂类
//抽象积木产品类,定义生产具体积木的接口produce()
class Block{
public:
//写成纯虚函数,一方面将该类变成抽象类,另一方面方便具体产品类实现多态
virtual void produce() = 0;
};
//具体圆形积木产品类
class CircleBlock: public Block{
public:
//重写父类虚函数
void produce() override {
cout<<"Circle Block"<<endl;
}
};
//具体方形积木产品类
class SquareBlock: public Block{
public:
//重写父类虚函数,使用override关键字编译器会检查重写是否正确,不是非要加
void produce() override
{
cout<<"Square Block"<<endl;
}
};
//抽象工厂类,提供一个抽象的接口用于创建对象。具体哪种对象还得用多态实现
class BlockFactory{
public:
//抽象的接口。 使用积木的基类指针作为返回值,其可以接收圆形或方形的积木对象(C++多态允许)
virtual Block* createBlock() = 0;
};
//具体圆形积木工厂类
class CircleBlockFactory:public BlockFactory{
public:
//重写接口函数
Block* createBlock() override
{
return new CircleBlock(); //堆区开辟内存存放积木对象
}
};
//具体方形积木工厂类
class SquareBlockFactory:public BlockFactory{
public:
//重写接口函数
Block* createBlock() override
{
return new SquareBlock(); //堆区开辟内存存放积木对象
}
};
//建立积木工厂系统
class BlockManageSystem{
private:
//使用Block*动态数组来记录积木信息
vector<Block *> blocks;
public:
//根据输入,建立积木生产函数。根据具体产品类型调用相对应的产品工厂
void produceBlocks(BlockFactory* factory, int num)
{
for(int i=0; i<num; i++)
{
Block* block = factory->createBlock();
this->blocks.push_back(block);
block->produce();
}
}
//由于具体积木存放在堆区,所以要使用delete进行内存释放
~BlockManageSystem(){
for(Block* block : blocks)
{
delete block;
}
}
//获取所有积木。第一个const修饰返回的引用,即使得到积木,也不能对积木进行修改。
//第二个const修饰this指针,保证this指针不能对积木进行修改
const vector<Block*> & getBlocks()const{
return blocks;
}
};
int main()
{
int produceNum; //生产次数
cin>>produceNum;
BlockManageSystem mySystem; //创建积木工厂系统
for(int i=0; i< produceNum; i++)
{
string blockType;
int blockNum;
//读取生产积木的类型和数量
cin>>blockType>>blockNum;
if(blockType == "Circle")
{
//需要使用工厂系统调用圆形积木工厂启动生产
mySystem.produceBlocks(new CircleBlockFactory(),blockNum);
}
else if (blockType == "Square")
{
//需要使用工厂系统调用方形积木工厂启动生产
mySystem.produceBlocks(new SquareBlockFactory(),blockNum);
}
}
return 0;
}
4.工厂模式应用场景
工厂方法模式使得每个工厂类的职责单一,每个工厂只负责创建一种产品,当创建对象涉及一系列复杂的初始化逻辑,而这些逻辑在不同的子类中可能有所不同时,可以使用工厂方法模式将这些初始化逻辑封装在子类的工厂中。