1. 工厂模式
工厂模式属于创建者模式,提供了一种创建对象的最佳方式。
工厂模式的实现方式有简单工厂模式、工厂方法模式、抽象工厂模式,每个实现方式都存在优和劣。
简单工厂模式与工厂模式的结构组成是:
代码语言:javascript复制1. 工厂类:工厂模式的核心类,会定义一个用于创建指定的具体实例对象的接口。(可分为抽象工厂和具体工厂)
2. 抽象产品类:是具体产品类的继承的父类或实现的接口。
3. 具体产品类:工厂类所创建的对象就是此具体产品实例。
以汽车厂为例:
Cars为汽车的抽象类(基类),接口函数为Show(),用于显示文本。
Benzi、Audi、Bmw为具体汽车品牌的类,它们都继承于Cars抽象类。
代码语言:javascript复制// 汽车抽象类
class Cars
{
public:
virtual ~Cars() {}
virtual void Show() = 0;
};
// 奔驰
class Benzi: public Cars
{
public:
void Show()
{
std::cout << "我是Benzi" << std::endl;
}
};
// 奥迪
class Audi: public Cars
{
public:
void Show()
{
std::cout << "我是Audi" << std::endl;
}
};
// 宝马
class Bmw: public Cars
{
public:
void Show()
{
std::cout << "我是Bmw" << std::endl;
}
};
CarsFactory为工厂类,类里实现根据汽车类型创建对应产品对象的CreateCars(CARS_TYPE type)函数。
代码语言:javascript复制enum CARS_TYPE
{
BENZI,
AUDI,
BMW
};
// 总车厂
class CarsFactory
{
public:
// 根据鞋子类型创建对应的鞋子对象
Cars *CreateCars(CARS_TYPE type)
{
switch (type)
{
case BENZI:
return new Benzi();
break;
case AUDI:
return new Audi();
break;
case BMW:
return new Bmw();
break;
default:
return NULL;
break;
}
}
};
main函数,先是构造了工厂对象,然后创建指定类型的具体产品对象,然后输出对应文本。因为采用的是new
的方式创建了对象,用完了要通过delete
释放资源资源。
int main()
{
// 构造工厂对象
CarsFactory carsFactory;
// 从工厂对象创建benzi对象
Cars *pBenzi = carsFactory.CreateCars(BENZI);
if (pBenzi != NULL)
{
pBenzi->Show();
// 释放资源
delete pBenzi;
pBenzi = NULL;
}
// 从工厂对象创建audi对象
Cars *pAudi = carsFactory.CreateCars(AUDI);
if (pAudi != NULL)
{
pAudi ->Show();
// 释放资源
delete pAudi ;
pAudi = NULL;
}
// 从工厂对象创建bmw对象
Cars *pBmw = carsFactory.CreateCars(BMW);
if (pBmw != NULL)
{
pBmw ->Show();
// 释放资源
delete pBmw ;
pBmw = NULL;
}
return 0;
}
2. 工厂方法模式
简单工厂模式存在最大的问题是违背了“开闭原则”,每当增加新的产品时,需要修改工厂类的逻辑。为了规避这种不足,同时很好的利用简单工厂模式的优点,这里介绍工厂方法模式。
工厂方法模式:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。示例如下:
代码语言:javascript复制#include <iostream>
#include <string>
// 产品基类
class Product {
public:
virtual void use() = 0;
};
// 具体产品类 A
class ConcreteProductA : public Product {
public:
void use() override {
std::cout << "Using ConcreteProductA" << std::endl;
}
};
// 具体产品类 B
class ConcreteProductB : public Product {
public:
void use() override {
std::cout << "Using ConcreteProductB" << std::endl;
}
};
// 工厂基类
class Factory {
public:
virtual Product* createProduct() = 0;
};
// 具体工厂类 A
class ConcreteFactoryA : public Factory {
public:
Product* createProduct() override {
return new ConcreteProductA();
}
};
// 具体工厂类 B
class ConcreteFactoryB : public Factory {
public:
Product* createProduct() override {
return new ConcreteProductB();
}
};
int main() {
// 使用具体工厂 A 创建产品 A
Factory* factoryA = new ConcreteFactoryA();
Product* productA = factoryA->createProduct();
productA->use();
// 使用具体工厂 B 创建产品 B
Factory* factoryB = new ConcreteFactoryB();
Product* productB = factoryB->createProduct();
productB->use();
delete factoryA;
delete productA;
delete factoryB;
delete productB;
return 0;
}
相较简单工厂模式,工厂方法模式更加符合开闭原则。工厂方法是使用频率最高的设计模式之一,是很多开源框架和API类库的核心模式。
3. 抽象工厂模式
汽车厂为了扩大业务,不只生产汽车了,还生产摩托车。抽象工厂模式可以创建多个工厂和多个产品族。
抽象工厂模式的组成:
代码语言:javascript复制1. 抽象工厂类:工厂方法模式的核心类,提供创建具体产品的接口,由具体工厂类实现。
2. 具体工厂类:继承于抽象工厂,实现创建对应具体产品对象的方式。
3. 抽象产品类:它是具体产品继承的父类(基类)。
4. 具体产品类:具体工厂所创建的对象,就是此类。
创建基类(抽象产品类):
代码语言:javascript复制// 汽车抽象类
class Cars
{
public:
virtual ~Cars() {}
virtual void Show() = 0;
};
// 奔驰
class BenziCar: public Cars
{
public:
void Show()
{
std::cout << "我是Benzi car" << std::endl;
}
};
// 摩托车抽象类
class Motors
{
public:
virtual ~Motors() {}
virtual void Show() = 0;
};
// 奔驰
class BenziMotor: public Motors
{
public:
void Show()
{
std::cout << "我是Benzi motor" << std::endl;
}
};
Factory为抽象工厂,提供了创建汽车CreateCars()和摩托车产品CreateMotors()对象的接口。
BenziProducer为具体工厂,实现了创建奔驰汽车和奔驰摩托车的方式。
代码语言:javascript复制// 总厂
class Factory
{
public:
virtual Cars *CreateCars() = 0;
virtual Motors *CreateMotors() = 0;
virtual ~Factory() {}
};
// benzi生产者/生产链
class BenziProducer : public Factory
{
public:
Cars *CreateCars()
{
return new BenziCar();
}
Motors *CreateMotors()
{
return new BenziMotor();
}
};
main函数,构造benzi工厂对象,然后创建benzi产品族的汽车和摩托车对象。同样,对象不再使用时,需要手动释放资源。
代码语言:javascript复制int main()
{
// ================ 生产Benzi流程 ==================== //
// 生产线
Factory *benziProducer = new BenziProducer();
// 生产汽车
Cars *benziCar = benziProducer ->CreateCars();
// 生产摩托车
Motors *benziMotor = benziProducer ->CreateMotors();
benziCar->Show();
benziMotor->Show();
// 释放资源
delete benziCar;
delete benziMotor;
delete benziProducer;
return 0;
}
适用场景:
- 一系列/一族产品需要被同时使用时,适合使用抽象工厂模式;
- 产品结构稳定,设计完成之后不会向系统中新增或剔除某个产品。