【C++】设计模式:工厂模式

2024-07-24 15:20:10 浏览数 (2)

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 释放资源资源。

代码语言:javascript复制
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;
}

适用场景:

  • 一系列/一族产品需要被同时使用时,适合使用抽象工厂模式;
  • 产品结构稳定,设计完成之后不会向系统中新增或剔除某个产品。

0 人点赞