工厂模式定义
工厂模式就是定义一个工厂类,提供创建产品对象的接口,根据工厂创建产品的方式可以分为以下三种:
简单工厂
简单工厂就是在工厂类中提供一个创建产品对象的接口,通过传入的产品类型来创建对应的产品对象。
UML图
优缺点
优点:
- 工厂没有过多的业务逻辑,逻辑简单
- 只需知道产品的类型,不用知道产品的类名
- 对象的创建和对象的使用完全分离
缺点:
- 支持产品单一,不易扩展,扩展不同族的产品时只能引入新的工厂类
- 产品过多时,工厂方法的代码会非常复杂,不易维护
- 违背了开闭原则
实现
enum class EProductType {
EPT_TypeA = 0,
EPT_TypeB,
EPT_TypeC
};
// 抽象产品类:抽象产品的方法
class AbstractProduct {
public:
virtual void printProduct() = 0;
};
// 具体产品A类
class ConcreteProductA : public AbstractProduct {
public:
void printProduct() override {
printf("product A");
}
};
// 具体产品B类
class ConcreteProductB : public AbstractProduct {
public:
void printProduct() override {
printf("product B");
}
};
// 具体产品C类
class ConcreteProductC : public AbstractProduct {
public:
void printProduct() override {
printf("product C");
}
};
// 工厂类
class Factory {
public:
static AbstractProduct* createProduct(EProductType type) {
switch (type)
{
case EProductType::EPT_TypeA:
return new ConcreteProductA();
break;
case EProductType::EPT_TypeB:
return new ConcreteProductB();
break;
case EProductType::EPT_TypeC:
break;
return new ConcreteProductC();
default:
break;
}
return nullptr;
}
};
工厂方法
工厂方法是对简单工厂模式进一步的抽象化,工厂类抽象后,派生出具体的工厂类和产品类型进行绑定。也就是具体的工厂生产同一种产品,不同的产品由不同的工厂生产。
UML图
优缺点
优点:
- 用户通过具体的工厂对象就能得到对应的产品,分离了创建和使用
- 易于扩展,只需多写一个工厂类即可
- 降低耦合度
- 满足开闭原则
缺点:
- 产品类型多,工厂类也就多,导致类的数量增多,增加系统复杂的
- 抽象产品只能生产一个类型的产品
实现
// 抽象产品类:抽象产品的方法
class AbstractProduct {
public:
virtual void printProduct() = 0;
};
// 具体产品A类
class ConcreteProductA : public AbstractProduct {
public:
void printProduct() override {
printf("product A");
}
};
// 具体产品B类
class ConcreteProductB : public AbstractProduct {
public:
void printProduct() override {
printf("product B");
}
};
// 抽象的创建者类:创建者抽象一个工厂方法,让子类去实现方法,返回具体的产品类型
class AbstractCreator {
public:
virtual AbstractProduct* factoryMethod() const = 0;
};
// 具体的创建者类型A
class ConcreteCreatorA : public AbstractCreator{
public:
AbstractProduct* factoryMethod() const override {
return new ConcreteProductA();
}
};
// 具体的创建者类型B
class ConcreteCreatorB : public AbstractCreator {
public:
AbstractProduct* factoryMethod() const override {
return new ConcreteProductB();
}
};
抽象工厂
抽象工厂是工厂方法模式的升级版本,工厂方法模式只能生产一个类型的产品,而抽象工厂提供了一个创建一系列有关联的产品对象的接口。
比如说工厂方法模式下,一个工厂只能生产空调,另一个工厂只能生产汽车;而抽象工厂是一个工厂A能够生产A品牌的空调和汽车,工厂B可以生产B品牌的空调和汽车。
UML
优缺点
优点:
- 一个工厂可以生产不同类型的产品
- 一个工厂能够保证生产的产品匹配
- 符合开闭原则
缺点:
- 引入多个接口和类,导致代码复杂
实现
// 抽象产品A
class AbstractProductA {
public:
virtual void printProductA() = 0;
};
// N品牌工厂的产品A
class ConcreteProductNA : public AbstractProductA{
public:
void printProductA() override {
printf("product N_A\n");
}
};
// M品牌工厂的产品A
class ConcreteProductMA : public AbstractProductA {
public:
void printProductA() override {
printf("product M_A\n");
}
};
// 抽象产品B
class AbstractProductB {
public:
virtual void printProductB() = 0;
};
// N品牌工厂的产品B
class ConcreteProductNB : public AbstractProductB {
public:
void printProductB() override
{
printf("product N_B\n");
}
};
// M品牌工厂的产品B
class ConcreteProductMB : public AbstractProductB {
public:
void printProductB() override
{
printf("product M_B\n");
}
};
// 抽象工厂
class AbstractFactory {
public:
virtual AbstractProductA* createProductA() = 0;
virtual AbstractProductB* createProductB() = 0;
};
// 具体N品牌工厂
class ConcreteFactoryN : public AbstractFactory {
public:
AbstractProductA* createProductA() override
{
return new ConcreteProductNA();
}
AbstractProductB* createProductB() override
{
return new ConcreteProductNB();
}
};
// 具体M品牌工厂
class ConcreteFactoryM : public AbstractFactory {
public:
AbstractProductA* createProductA() override
{
return new ConcreteProductMA();
}
AbstractProductB* createProductB() override
{
return new ConcreteProductMB();
}
};
应用场景区分
三种工厂模式需要分清对应的适用场景才能使用,否则会导致后期需要重构代码。
下面分别列举不同模式的适用条件:
简单工厂模式:
- 确保产品能够抽象化
- 不关心产品的类型
- 后期不太可能会扩展新的产品(因为扩展新产品需要修改创建方法的代码)
- 只需通过类型值来区分生产产品的类型
工厂方法模式:
- 确保产品能够抽象化
- 不关心产品的类型
- 后期可能需要扩展新的产品
抽象工厂模式:
- 创建的产品是一系列相关的产品族(包含不同类型的产品)
- 相同类型的产品能够抽象化