• 面向对象设计与分析(42)工厂方法模式


    定义

    工厂方法模式,定义一个用于创建对象的接口(工厂方法),返回对象基类,让子类去实现该接口,从而返回具体的子类对象。
    在这里插入图片描述
    结构
    工厂方法模式包含以下主要角色:

    • 抽象产品(Product):定义产品的接口,是工厂方法模式创建的对象的超类型。
    • 具体产品(Concrete Product):实现抽象产品接口的具体类。
    • 抽象工厂(Creator):声明创建产品对象的工厂方法,是工厂方法模式的核心。
    • 具体工厂(Concrete Creator):实现抽象工厂接口,返回具体产品的实例。

    工作原理

    1. 客户端通过调用抽象工厂中的工厂方法来创建产品对象,而不需要关心具体产品是如何创建的。
    2. 具体工厂实现了抽象工厂中的工厂方法,根据客户端的需求创建具体产品对象。
    3. 具体产品是抽象产品的具体实现,它们实现了抽象产品定义的接口。

    示例

    以下是一个简单的 C++ 示例:

    #include 
    
    // 抽象产品类
    class Product {
    public:
        virtual ~Product() {}
    public:
        virtual void Operation() const = 0;
    };
    
    // 具体产品类 A
    class ConcreteProductA : public Product {
    public:
        void Operation() const override {
            std::cout << "ConcreteProductA operation." << std::endl;
        }
    };
    
    // 具体产品类 B
    class ConcreteProductB : public Product {
    public:
        void Operation() const override {
            std::cout << "ConcreteProductB operation." << std::endl;
        }
    };
    
    // 抽象工厂类
    class Creator {
    public:
        virtual ~Creator() {}
    public:
        virtual Product* factoryMethod() const = 0;
    };
    
    // 具体工厂类 A
    class ConcreteCreatorA : public Creator {
    public:
        Product* factoryMethod() const override {
            return new ConcreteProductA();
        }
    };
    
    // 具体工厂类 B
    class ConcreteCreatorB : public Creator {
    public:
        Product* factoryMethod() const override {
            return new ConcreteProductB();
        }
    };
    
    int main() {
        // 使用具体工厂 A 创建具体产品 A
        Creator* creatorA = new ConcreteCreatorA();
        Product* productA = creatorA->factoryMethod();
        productA->operation();
        delete creatorA;
        delete productA;
    
        // 使用具体工厂 B 创建具体产品 B
        Creator* creatorB = new ConcreteCreatorB();
        Product* productB = creatorB->factoryMethod();
        productB->operation();
        delete creatorB;
        delete productB;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    在这个示例中,Product 是抽象产品类,定义了产品的操作接口。ConcreteProductA 和 ConcreteProductB 是具体产品类,分别实现了抽象产品类的接口。Creator 是抽象工厂类,定义了工厂方法 factoryMethod(),负责创建产品对象。ConcreteCreatorA 和 ConcreteCreatorB 是具体工厂类,分别实现了工厂方法,用于创建具体产品 A 和 B。客户端通过具体工厂类来创建具体产品对象,而不需要直接与具体产品类交互。

    实际应用

    该模式的缺点显而易见,我们需要为每一类Product定义一个Creator类,同时需要为每个具体的Product实现具体的Creator类,十分繁琐。

    当然,我们可以通过参数化工厂方法来解决这一问题,这又绕回到了简单工厂模式:

    // 工厂类
    class SimpleFactory {
    public:
        static Product* createProduct(char type) {
            if (type == 'A') {
                return new ConcreteProductA();
            } else if (type == 'B') {
                return new ConcreteProductB();
            }
            return nullptr;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    createProduct方法通过传递不同的参数来实例化不同的子类。

    我们可以借助模板,来避免反复编写重复的Creator类:

    class Creator {
    	public:
    		virutal	~Creator() = default;
    	public:
    		virtual Product* CreateProduct() = 0;
    };
    
    template<typename Product>
    class StandardCreator : public Creator {
    	public:
    		virtual Product* CreateProduct() {
    			return new Product;
    		}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    当然,还是有一定的缺陷,只能使用无参构造,或者说只能使用一种类型的构造。

    实际工程里,我经常把工厂方法内嵌到产品类中,这样不用工厂类。

    class Product {
    	public:
    		~Product() = default;
    };
    
    class ConcreateProduct {
    	public:
    		~Product() = default;
        public:
        	static ConcreateProduct* CreateConcreateProduct() {
                return new ConcreateProduct;
            }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    工厂方法是static的,因此可以脱离对象调用。

  • 相关阅读:
    Qt day2
    全局变量和静态变量的初始化
    RedissonClient中Stream流的简单使用
    yield方法的使用
    搞懂 MySql 的架构和执行流程
    第五十五周总结——十一月月底总结
    设计模式——责任链
    lambda表达式
    J2EE从入门到入土02.Set及Map集合解析
    JS 原生实现触底加载
  • 原文地址:https://blog.csdn.net/HandsomeHong/article/details/138048203