工厂模式
工厂模式,是创建型设计模式的一种,也是最简单的一种。正常情况下,工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,或者需要添加新产品,就不得不修改工厂类的逻辑,这样就会造成逻辑过于复杂的问题,整个系统都会受到影响,并且违背了设计模式的“开闭原则”。
将原来的工厂设计成抽象父类,只负责定义公共接口而不定义创建行为,然后继承出一系列子类,不妨称之为具体工厂,负责创建产品。即将产品的创建行为延迟到具体工厂中完成,由它们决定怎样创建产品。
一旦需要创建新的产品,则新建一个具体工厂,符合了“开闭原则”。
使用步骤
步骤1:创建抽象工厂类,定义公共接口;
步骤2:创建抽象产品类 ,定义公共接口;
步骤3:创建具体产品类(继承抽象产品类),定义具体产品行为;
步骤4:创建具体工厂类(继承抽象工厂类),定义具体工厂行为;
步骤5:外界通过调用具体工厂类class object的方法,创建具体产品类实例
应用实例
情景:一间仅生产A型产品的加工厂,随着客户需求的变化,需要生产B类产品。
壁垒:改变原有加工厂的配置成本太大,假设下一次客户需要再发生变化,再次改变将再次增大的成本。
方案:置办分厂B来生产B型产品。
步骤1:创建抽象工厂类,定义公共接口
class Factory {
public:
virtual Product * Manufacture() = 0;
};
步骤2:创建抽象产品类 ,定义具体产品的公共接口
class Product {
public:
virtual void Show() = 0;
};
步骤3:创建具体产品类,定义具体产品
//A型产品
class ProductA : public Product {
public:
void Show() {
cout << "生产出了A型产品" << endl;
}
};
//新增B型产品需求
class ProductB : public Product {
public:
void Show() {
cout << "生产出了B型产品" << endl;
}
};
步骤4:创建具体工厂类,定义行为
// 工厂A — 生产A型产品
class FactoryA : public Factory {
public:
Product * Manufacture() {
return new ProductA();
}
};
// 新建工厂B用于生产B型产品
class FactoryB : public Factory {
public:
Product * Manufacture() {
return new ProductB();
}
};
步骤5:外部创建具体类对象,创建相应的产品
int main()
{
Factory *mFactory = new FactoryB();
cout << "新增B型产品需求\n";
cout << "新建工厂B用于生产B型产品\n";
mFactory->Manufacture()->Show();
return 0;
}
优点
工厂模式的优点在于,每个具体工厂类只负责创建对应的产品,逻辑简单清晰。需要新增一种产品时,需要增加创建它的具体工厂类,而不是更改原来的代码,符合开闭原则。因为产品和工厂角色都使用了多态,所以外部无需知道具体产品创建的细节就可以实现功能的扩展。
缺点
添加新产品时,除了增加新产品类还要提供对应的具体工厂类,类的个数将成对增加,增加了复杂度和开销。另一个问题是一个具体工厂只能创建一类产品。
抽象工厂模式
工厂模式存在一个严重的问题:一个具体工厂只能创建一类产品,而在实际过程中,一个工厂往往需要生产多类产品。为了解决这个问题,又引入了一种新的设计模式:抽象工厂模式。
抽象工厂模式,提供一个创建一系列相关对象的接口,而无须指定它们具体的类,具体的工厂负责实现具体的产品实例。
允许使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,这样就可以从具体产品中被解耦。
步骤1: 创建抽象工厂类;
步骤2: 创建抽象产品族类;
步骤3: 创建抽象产品类(继承抽象产品族类);
步骤4: 创建具体产品类(继承抽象产品类);
步骤5: 创建具体工厂类(继承抽象工厂类);
步骤6: 外部实例化具体的工厂类,创建具体产品类的实例。
与工厂模式的区别: 多了抽象产品族类,使得每个工厂可以创建多种类的产品,而工厂方法每个工厂只能创建一类。
应用实例
情景:某公司有两间分布在不同区域的工厂产线,A厂负责生产机械臂产品,B厂负责生产计算机产品。随着客户需求的变化,A厂所在地的客户需要计算机产品产品,B厂所在地的客户需要机械臂产品。
壁垒:没有资源和成本在当地分别开设多一家分厂。
解决方案:在原有的两家工厂里增设生产需求的功能,即A、B两厂都能独立生产机械臂+计算机产品。
步骤1: 创建抽象工厂类,定义公共行为
class Factory {
public:
virtual Product * ManufactureRobotArm() = 0; //生产机械臂产品
virtual Product * ManufactureComputer() = 0; //生产计算机产品
};
步骤2: 创建抽象产品族类 ,定义产品的公共接口
class ProductFamily {
public:
virtual void Show() = 0;
};
步骤3:创建抽象产品类,继承自抽象产品族,这样就可以定义多种种类的产品,这一步除了继承动作不做任何操作
//机械臂抽象产品类
class ProductRobotArm : public ProductFamily {};
//计算机抽象产品类
class ProductComputer : public ProductFamily {};
步骤4:创建具体产品类,继承抽象产品类,定义具体产品
原本的只有两种产品,A厂负责生产机械臂,型号为A型机械臂,B厂负责生产计算机,型号为B型计算机。
//A型机械臂
class RobotArmAType : public ProductRobotArm {
public:
void Show() {
cout << "生产A型机械臂" << endl;
}
};
//B型计算机
class ComputerBType : public ProductComputer {
public:
void Show() {
cout << "生产B型计算机" << endl;
}
};
现在客户有了新的需求,A厂区域的客户需要计算机产品,定为A型计算机,B厂区域的客户需要机械臂,定为B型机械臂
//新增加的A型计算机产品需求,由A厂负责新增生产计划
class ComputerAType : public ProductComputer {
public:
void Show() {
cout << "生产A型计算机" << endl;
}
};
//新增加的B型机械臂产品需求,由B厂负责新增生产计划
class RobotArmBType : public ProductRobotArm {
public:
void Show() {
cout << "生产B型机械臂" << endl;
}
};
步骤5:创建具体工厂类,继承自抽象工厂类,定义创建对应具体产品实例的方法
A厂原本只有机械臂生产,随着客户需求的变动,新增加了计算机生产计划。
//A厂 — 生产A型机械臂+A型计算机产品
class FactoryA : public Factory {
public:
//原有的机械臂生产
ProductFamily * ManufactureRobotArm() {
return new RobotArmAType();
}
//新增A型计算机产品生产计划
ProductFamily * ManufactureComputer() {
return new ComputerAType();
}
};
B厂原本只有计算机生产,随着客户需求的变动,新增加了机械臂生产计划。
class FactoryB : public Factory {
public:
//B厂原有的计算机生产
ProductFamily * ManufactureComputer() {
return new ComputerBType();
}
//B厂新增加的机械臂生产计划
ProductFamily * ManufactureRobotArm() {
return new RobotArmBType();
}
};
步骤6:外部通过实例化具体工厂类,创建具体产品
int main()
{
//生产工作流程
Factory *mFactoryA = new FactoryA();
Factory *mFactoryB = new FactoryB();
std::cout << "A厂原本负责生产机械臂,型号为A型机械臂: " << std::endl;
mFactoryA->ManufactureRobotArm()->Show();
std::cout << "A厂新增加计算机生产产线,型号为A型计算机: " << std::endl;
mFactoryA->ManufactureComputer()->Show();
std::cout << std::endl;
std::cout << "B厂原本负责生产计算机,型号为B型计算机: " << std::endl;
mFactoryB->ManufactureComputer()->Show();
std::cout << "B厂新增加机械臂生产产线,型号为B型机械臂: " << std::endl;
mFactoryB->ManufactureRobotArm()->Show();
return 0;
}