在 23 种设计模式中,总体来说设计模式分为三大类:
其中,创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。本文将介绍工厂方法模式、抽象工厂模式 2 种,其中,工厂方法模式一般可以分为简单工厂模式及工厂模式。
简单工厂模式是一种创建型设计模式,旨在引入一个工厂类来创建不同类型的对象,无需直接实例化这些对象。它提供了一种灵活的方式来管理对象的创建,使代码更易于维护和扩展。
简单工厂模式又叫静态方法模式(因为工厂类定义了一个静态方法)。在现实生活中,工厂负责生产产品;同样在设计模式中,简单工厂模式可以理解为负责生产对象的一个类,称为“工厂类”。
简单工厂模式将“类实例化的操作”与“使用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。使用者可以直接消费产品而不需要知道其生产的细节。
组成(角色):
抽象产品(Product):具体产品的父类,描述产品的公共接口。
具体产品(Concrete Product):抽象产品的子类,描述生产的具体产品。
工厂(Creator):被外界调用,根据传入不同参数从而创建不同具体产品类的实例。
a. 创建抽象产品类,定义具体产品的公共接口。
b. 创建具体产品类(继承抽象产品类),定义生产的具体产品。
c. 创建工厂类,通过创建静态方法根据传入不同参数从而创建不同具体产品类的实例。
d. 外界通过调用工厂类的静态方法,传入不同参数从而创建不同具体产品类的实例。
当前我有三个产品,华为汽车(HuaweiCar)、小米汽车(XiaomiCar)、特斯拉汽车(TeslaCar),该三种产品都有共同的属性电池,共有方法前进、后退; 于是我们决定将该三种产品,抽象出一个叫做汽车(Car)的类,代码如下:
// 车辆接口定义了车辆应该支持的基本操作
class Car {
public:
// 虚析构函数,确保派生类的正确清理
virtual ~Car() {}
// 前进
virtual void Forward() = 0;
// 后退
virtual void Backward() = 0;
protected:
int m_nBattery; // 电池
};
然后分别定义三个产品类:
// 华为类,实现了车辆接口。
class HuaweiCar : public Car {
public:
HuaweiCar();
virtual void Forward() override;
virtual void Backward() override;
};
// 小米类,实现了车辆接口
class XiaomiCar : public Car {
public:
XiaomiCar();
virtual void Forward() override;
virtual void Backward() override;
};
// 特斯拉类,实现了车辆接口
class TeslaCar : public Car {
public:
TeslaCar();
virtual void Forward() override;
virtual void Backward() override;
};
然后定义工厂类,该类的作用是生产产品(new 处所需的对象),如下:
// 简单工厂模式
class SimpleCarFactory {
public:
static Car* createCar(CarType nType_)
{
switch (nType_)
{
case CarType::HUAWEI:
return new HuaweiCar();
case CarType::XIAOMI:
return new XiaomiCar();
case CarType::TESLA:
return new TeslaCar();
default:
throw std::invalid_argument("Unknown car type");
}
}
};
至此,就完成了简单工厂模式,只需要在需要对象的地方,调用工厂,传入想要的对象类型,即可得到对象。但是,简单工厂模式有如下缺陷:
例如,若在增加理想汽车类,那么工厂类的代码就必须更改如下:
// 简单工厂模式
class SimpleCarFactory {
public:
static Car* createCar(CarType nType_)
{
switch (nType_)
{
case CarType::HUAWEI:
return new HuaweiCar();
case CarType::XIAOMI:
return new XiaomiCar();
case CarType::TESLA:
return new TeslaCar();
case CarType::LiXIANG:
return new LiXiangCar(); // 新增代码
default:
throw std::invalid_argument("Unknown car type");
}
}
};
工厂方法模式允许我们在不直接实例化对象的情况下,通过使用工厂来创建不同类型的产品对象。相对于简单工厂模式,这种方式使得添加新产品类时,只需添加相应的工厂类即可,无需修改现有代码,符合开闭原则。
组成(角色):
相对于简单工厂模式,工厂方法模式其实就是每个产品类都有对应的工厂,而这些具体的工厂类都是基于同一个抽象工厂类,每个产品都拥有自己对应的工厂,那么,新增产品类时,只需要新增对应的工厂类即可。
同样是简单工厂模式中的例子,如今存在 3 款产品,为每一种产品都设计一个工厂,而工厂目前只有一个任务,能够生产产品(车),于是我们定义工厂类:
// 工厂方法模式
class CarFactory
{
public:
virtual std::unique_ptr<Car> createCar() = 0;
};
上述的工厂只是定义了创建产品的接口,而实现则由各自产品对应的工厂去实现:
// 具体工厂类:华为汽车工厂
class HuaweiCarFactory : public CarFactory {
public:
std::unique_ptr<Car> createCar() override {
return std::make_unique<HuaweiCar>();
}
};
// 具体工厂类:小米汽车工厂
class XiaomiCarFactory : public CarFactory {
public:
std::unique_ptr<Car> createCar() override {
return std::make_unique<XiaomiCar>();
}
};
// 具体工厂类:特斯拉汽车工厂
class TeslaCarFactory : public CarFactory {
public:
std::unique_ptr<Car> createCar() override {
return std::make_unique<TeslaCar>();
}
};
上述代码即工厂方法模式的核心,主要思想即:各自产品拥有各自的工厂!这种模式的优点在于,当增加新的产品时,仅需要新增产品类及对应产品的工厂,无需修改原有的代码,即对扩展开放,对修改关闭。
抽象工厂模式通常涉及一族相关的产品,每个具体工厂类负责创建该族中的具体产品。客户端通过使用抽象工厂接口来创建产品对象,而不需要直接使用具体产品的实现类。
抛开上述描述不谈,最简单的理解方式就是:产品不再单一,工厂职责也不再单一。这里引入品牌和产品的概念,其实也就是产品族和产品等级的概念。
比如,将上述的例子扩展,华为不仅有车这一个产品,还有手机这一个产品,华为就是品牌,车和手机就是产品,小米同理。此时,按照工厂方法模式,我们可以这样做:
这样做当然可以,可以看作华为的车工厂和手机工厂完全是两个独立的东西,没有任何联系。抽象工厂模式可以理解为:合并 2 个相关的工厂,让该工厂既能够生产手机、又能够生产车。看如下代码:
// 定义手机的基本操作
class Phone {
public:
Phone();
// 虚析构函数,确保派生类的正确清理
virtual ~Phone() {}
// call
virtual void Call() = 0;
};
// 华为手机
class HuaweiPhone : public Phone
{
public:
HuaweiPhone();
virtual void Call() override;
};
// 华为手机
class XiaomiPhone : public Phone
{
public:
XiaomiPhone();
virtual void Call() override;
};
工厂如下定义:
// 抽象工厂模式
class Factory
{
public:
virtual std::unique_ptr<Car> createCar() = 0; // 生产车的接口
virtual std::unique_ptr<Phone> createPhone() = 0; // 生产手机的接口
};
// 具体工厂类:华为工厂
class HuaweiFactory : public Factory {
public:
std::unique_ptr<Car> createCar() override {
return std::make_unique<HuaweiCar>();
}
std::unique_ptr<Phone> createPhone() override {
return std::make_unique<HuaweiPhone>();
}
};
// 具体工厂类:小米工厂
class XiaomiFactory : public Factory {
public:
std::unique_ptr<Car> createCar() override {
return std::make_unique<XiaomiCar>();
}
std::unique_ptr<Phone> createPhone() override {
return std::make_unique<XiaomiPhone>();
}
};
优点:
缺点:
以上完整代码请见 GitHub 仓库。