• C++设计模式——工厂模式Factory Method


    动机(Motivation)

    • 在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。
    • 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?

    模式定义

    定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,手段:虚函数)到子类。 ——《设计模式》GoF

    模式举例

    之前在观察者模式中提到了文件分割器的例子,这里再用文件分割器例子来说明一下。文件分割器可能不止有一种二进制文件分割器,可能还会有文本文件分割器、图像文件分割器、视频文件分割器等等,面对不同的需求,需要经常创建不同的具体类型。

    class ISplitter{
    public:
        virtual void split()=0;
        virtual ~ISplitter() {}
    };
    
    class BinarySplitter : public ISplitter{
    
    };
    
    class TxtSplitter: public ISplitter{
    
    };
    
    class PictureSplitter: public ISplitter{
    
    };
    
    class VideoSplitter: public ISplitter{
    
    };
    
    class MainForm : public Form{
        TextBox* txtFilePath;
        TextBox* txtFileNumber;
        ProgressBar* progressBar;
    
    public:
        void Button1_Click()
        {
            ISplitter * splitter= new BinarySplitter();//依赖具体类
            splitter->split();
    
        }
    };

    但这样设计一旦需求发生了变化,就要不断地更改代码,splitter依赖具体的实现类。

    使用工厂模式可以解决这个问题。定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。

    //抽象类
    class ISplitter{
    public:
        virtual void split()=0;
        virtual ~ISplitter(){}
    };
    
    
    //工厂基类
    class SplitterFactory{
    public:
        virtual ISplitter* CreateSplitter()=0;
        virtual ~SplitterFactory(){}
    };
    
    
    //具体类
    class BinarySplitter : public ISplitter{
        
    };
    
    class TxtSplitter: public ISplitter{
        
    };
    
    class PictureSplitter: public ISplitter{
        
    };
    
    class VideoSplitter: public ISplitter{
        
    };
    
    //具体工厂
    class BinarySplitterFactory: public SplitterFactory{
    public:
        virtual ISplitter* CreateSplitter(){
            return new BinarySplitter();
        }
    };
    
    class TxtSplitterFactory: public SplitterFactory{
    public:
        virtual ISplitter* CreateSplitter(){
            return new TxtSplitter();
        }
    };
    
    class PictureSplitterFactory: public SplitterFactory{
    public:
        virtual ISplitter* CreateSplitter(){
            return new PictureSplitter();
        }
    };
    
    class VideoSplitterFactory: public SplitterFactory{
    public:
        virtual ISplitter* CreateSplitter(){
            return new VideoSplitter();
        }
    };
    
    
    class MainForm : public Form
    {
        SplitterFactory*  factory;//工厂
    public:
        MainForm(SplitterFactory*  factory){
            this->factory=factory;//区分函数成员与参数
        }
        void Button1_Click(){
            ISplitter * splitter= factory->CreateSplitter(); //多态new
            splitter->split();
        }
    };
    
    //MainForm没有依赖具体类了

    结构(Structure)

    要点总结

    • Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
    • Factory Method模式通过面向对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。
    • Factory Method模式解决“单个对象”的需求变化。缺点在于要求创建方法/参数相同。

    基本代码

    #include <iostream>
    using namespace std;
    
    class Product {
    public:
        virtual ~Product(){}
        virtual void Operation() = 0;
    };
    
    class ConcreteProductA : public Product {
    public:
        void Operation() { cout << "ConcreteProductA" << endl; }
    };
    
    class ConcreteProductB : public Product {
    public:
        void Operation() { cout << "ConcreteProductB" << endl; }
    };
    
    class Creator{
    public:
        virtual Product* FactoryMethod() = 0;
        virtual ~Creator(){}
    };
    
    class ConcreteCreatorA : public Creator {
    public:
        Product* FactoryMethod() { return new ConcreteProductA(); }
    };
    
    class ConcreteCreatorB : public Creator {
    public:
        Product* FactoryMethod() { return new ConcreteProductB(); }
    };
    
    int main() {
        Creator* ca = new ConcreteCreatorA();
        Product* pa = ca->FactoryMethod();
        pa->Operation(); // ConcreteProductA
    
        Creator* cb = new ConcreteCreatorB();
        Product* pb = cb->FactoryMethod();
        pb->Operation(); // ConcreteProductB
    
        delete ca;
        delete pa;
        delete cb;
        delete pb;
    
        return 0;
    }
  • 相关阅读:
    机器学习算法优秀性:衡量指标
    MapReduce and Pregel
    K-d 树对聚类算法进行预处理
    论文中的算法描述 By 薛磊
    批判性思维《描述性假设》
    论文中的数学符号使用
    HOOK别人的dylib(HOOK cydia里面的插件)
    关于某听书软件的开通20年会员的心路历程
    Aspects 源码学习
    Undefined symbols for architecture arm64(其cpu架构)
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/12695582.html
Copyright © 2020-2023  润新知