设计模式-工厂模式

发布于:2025-02-19 ⋅ 阅读:(33) ⋅ 点赞:(0)

设计模式 - 工厂模式

工厂模式(Factory Pattern)是一种创建型设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,从而使得一个类的实例化延迟到子类。工厂模式通过将对象创建的逻辑抽象化,减少了客户端代码与具体类之间的耦合。

工厂模式通常通过工厂类来实现,工厂类负责根据需求创建不同的对象。工厂模式常见的有以下几种变种:

  1. 简单工厂模式(Simple Factory Pattern)
  2. 工厂方法模式(Factory Method Pattern)
  3. 抽象工厂模式(Abstract Factory Pattern)

1. 简单工厂模式

  1. 定义:

简单工厂模式定义了一个工厂类,它根据不同的输入条件创建不同的产品类实例。客户端通过工厂类来获取所需的对象,而不需要关心对象是如何创建的。
示例:

假设我们有两种产品:ProductA 和 ProductB。客户端通过简单工厂来选择要创建的产品。

  1. 结构框图
    在这里插入图片描述

  2. 代码实现

#include <iostream>

// 产品基类
class Product {
public:
    // 纯虚函数 -> 实现多态(统一抽象化接口)
    virtual void showProduct() = 0;
    virtual ~Product() = default;
};

// 具体产品A
class ConcreteProductA : public Product {
public:
    // 重写基类虚函数
    void showProduct() override {
        std::cout << "Create Product A" << std::endl;
    }
};

// 具体产品B
class ConcreteProductB : public Product {
public:
    // 重写基类虚函数
    void showProduct() override {
        std::cout << "Create Product B" << std::endl;
    }
};

// 简单工厂类, 用于去创建产品
class SimpleFactory {
public:
    Product* createProduct(char type) {
        if (type == 'A') {
            return new ConcreteProductA();
        } else if (type == 'B') {
            return new ConcreteProductB();
        } else {
            return nullptr;
        }
    }
};

int main() {
    // 通过简单工厂创建产品
    SimpleFactory myfactory;
    
    // 利用简单工厂创建产品A
    Product* productA = myfactory.createProduct('A');
    if(productA)
    {
        productA->showProduct();
    }
    
    // 利用简单工厂创建产品B
    Product* productB = myfactory.createProduct('B');
    if(productB)
    {
        productB->showProduct();
    }
    
    delete productA;
    delete productB;
    return 1;
}

说明:

  • 优点:客户端不需要知道具体类的实现,代码解耦。
  • 缺点:随着产品种类的增加,工厂类变得越来越庞大,不符合开闭原则(对修改关闭,对扩展开放)。

2. 工厂方法模式(Factory Method Pattern)

  1. 定义:
  • 封闭-开放 原则:新添加的功能不用去修改以前已经创建的类的内容

工厂方法模式将对象的创建推迟到子类,允许子类决定要创建的对象类型。通过定义一个抽象工厂接口,每个具体工厂只负责创建**一个**特定类型的对象。
示例:

  • 添加一个新的产品,只用新建其对应的产品类以及对于产品工厂类
    将简单工厂模式中的产品创建移交给具体工厂类来实现。
  1. 结构框图
    在这里插入图片描述

  2. 代码实现

#include <iostream>

class Product 
{
public:
    virtual void showProduct() = 0;   // 
    virtual ~Product() = default;
};

class ConcreteProductA : public Product {
public:
    void showProduct() override
    {
        std::cout << "A product show (method factory)\n";
    }
};

class ConcreteProductB : public Product {
public:
    void showProduct() override
    {
        std::cout << "B product show (method factory)\n";
    }
};

// 工厂接口
class Factory {
public:
    virtual Product* createProduct(void) = 0;
    virtual ~Factory() = default;
};

// 具体工厂A接口
class ConcreteFactoryA : public Factory {
    Product* createProduct(void) override
    {
        return new ConcreteProductA;
    }
};

// 具体工厂B接口
class ConcreteFactoryB : public Factory {
    Product* createProduct(void) override
    {
        return new ConcreteProductB;
    }
};

int main()
{
    Factory* factoryA  = new ConcreteFactoryA;
    Factory* factoryB  = new ConcreteFactoryB;

    Product* productA = factoryA->createProduct();
    Product* productB = factoryB->createProduct();

    productA->showProduct();
    productB->showProduct();

    delete factoryA;
    delete factoryB;
    delete productA;
    delete productB;
    return 1;
}

新添加一个产品C只用,添加ConcreteProductCConcreteFactoryC,但是不用去修改已经存在的类,符合封闭-开放原则的封闭原则。

  1. 说明:
  • 优点:工厂方法模式将创建对象的工作推迟到子类,使得系统易于扩展,可以通过添加新的具体工厂来支持新产品。
  • 缺点:每增加一种新产品,都需要增加一个新的工厂类,系统类的数量会迅速增加。

3. 抽象工厂模式(Abstract Factory Pattern)

定义:

抽象工厂模式提供一个接口,用于创建**一系列**相关或依赖的对象,而无需指定它们具体的类。允许创建一组相关的对象(产品族),而每个具体的工厂都负责创建一组产品。常用于产品族的创建,即一组相互关联的对象的创建(比如跨平台 GUI 界面的不同风格)。
示例:

我们有两种平台(Windows 和 Linux),每个平台有不同的按钮和输入框。抽象工厂模式通过平台工厂来创建相应的控件。

#include <iostream>

// 按钮接口
class Button {
public:
    virtual void render() = 0;
    virtual ~Button() = default;
};

// 输入框接口
class TextField {
public:
    virtual void render() = 0;
    virtual ~TextField() = default;
};

// 具体按钮类:Windows
class WindowsButton : public Button {
public:
    void render() override {
        std::cout << "Rendering Windows Button" << std::endl;
    }
};

// 具体按钮类:Linux
class LinuxButton : public Button {
public:
    void render() override {
        std::cout << "Rendering Linux Button" << std::endl;
    }
};

// 具体输入框类:Windows
class WindowsTextField : public TextField {
public:
    void render() override {
        std::cout << "Rendering Windows TextField" << std::endl;
    }
};

// 具体输入框类:Linux
class LinuxTextField : public TextField {
public:
    void render() override {
        std::cout << "Rendering Linux TextField" << std::endl;
    }
};

// 抽象工厂接口
class GUIFactory {
public:
    virtual Button* createButton() = 0;
    virtual TextField* createTextField() = 0;
    
    /*
    父类析构函数为虚函数的原因:在多态情况下正确地执行派生类的析构操作
    */
    virtual ~GUIFactory() = default;
};

// 具体工厂类:Windows
class WindowsFactory : public GUIFactory {
public:
    Button* createButton() override {
        return new WindowsButton();
    }

    TextField* createTextField() override {
        return new WindowsTextField();
    }
};

// 具体工厂类:Linux
class LinuxFactory : public GUIFactory {
public:
    Button* createButton() override {
        return new LinuxButton();
    }

    TextField* createTextField() override {
        return new LinuxTextField();
    }
};

int main() {

    GUIFactory* factory = new WindowsFactory();
    Button* button = factory->createButton();
    TextField* textField = factory->createTextField();

    button->render();    // 输出: Rendering Windows Button
    textField->render(); // 输出: Rendering Windows TextField

    delete button;
    delete textField;
    delete factory;

    factory = new LinuxFactory();
    button = factory->createButton();
    textField = factory->createTextField();

    button->render();    // 输出: Rendering Linux Button
    textField->render(); // 输出: Rendering Linux TextField

    delete button;
    delete textField;
    delete factory;

    return 0;
}

说明:

  • 优点:能够**创建一系列**相关的产品,客户端不需要知道具体类的实现,只需依赖工厂接口。
  • 缺点:增加了接口和类的数量,如果产品种类过多,抽象工厂可能变得复杂。

4. 工厂方法模式与抽象工厂模式的区别

特性 工厂方法模式(Factory Method) 抽象工厂模式(Abstract Factory)
创建对象的方式 每个工厂方法只负责创建一个具体产品。 创建一系列相关或依赖的产品,通常创建多个产品。
产品的数量 通常每个工厂类创建一个产品。 每个工厂类负责创建多个产品(一个产品族)。
工厂的数量 每个具体工厂类负责创建一个特定的产品。 每个具体工厂类负责创建一系列相关的产品。
产品的关系 产品之间没有严格的依赖关系。 产品之间通常有一定的关联,属于同一个产品族(如同一平台下的按钮和文本框)。
扩展性 新产品需要新建一个工厂类来负责创建它。 新产品族需要新建一个工厂类来创建一组相关产品。
适用场景 产品种类不多时,或者系统只需要创建单一类型的对象时。 当需要创建多个相关产品时,尤其是多个产品属于同一产品族时。

总结:

  • 工厂方法模式关注于**单一产品**的创建,每个具体工厂负责创建一个特定的产品。适用于产品种类少且扩展简单的场景。
  • 抽象工厂模式关注于**一系列相关产品**的创建,每个具体工厂负责创建多个相关的产品,适用于需要创建多个相关对象并保证它们兼容的场景,如跨平台的 UI 库。

两者的主要区别在于创建产品的数量和产品之间的关系,工厂方法模式偏向于单一产品的创建,而抽象工厂模式偏向于创建一系列相关的产品。