• 【设计模式】Head First 设计模式——工厂方法模式 C++实现


    设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。

    设计思想

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

    动机

    在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。

    如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?

    Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系会导致软件的脆弱。

    Factory Method模式通过面向对象的收发,将所要创建的具体对象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种耦合关系。

    Factory Method 模式解决“单个对象”的需求变化。缺点在于创建方法、参数需要相同。

    业务场景

    在 MainForm 中需要对文件进行分解操作,但是分解的文件可能是二进制文件,文本文件,图片文件等等,这时候我们需要在 MainForm 创建对应的对象,然后调用分解函数。

    一个非常直观的思路是:

    class ISplitter {
    public:
        virtual void split() = 0;
        virtual ~ISplitter() {
        }
    };
    
    class BinarySplitter : public ISplitter {
    //实现分解二进制文件
    };
    
    class TxtSplitter : public ISplitter {
    //实现分解TXT文件
    };
    
    class PictureSplitter : public ISplitter {
    //实现分解图片文件
    };
    
    class VideoSplitter : public ISplitter {
     //实现分解视频文件   
    };
    
    class MainForm : public Form {
    public:
        void Button1_Click() {
            ISplitter* splitter = new BinarySplitter();  
            splitter->split();
        }
    };
    
    • 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

    这是很自然的一种写法,问题的关键在于这一句代码:

    ISplitter* splitter = new BinarySplitter();  
    
    • 1

    在等号的左边,是一个抽象类,属于抽象依赖(编译时依赖),但是等号的右边,是一个具体类,属于细节依赖。根据依赖倒置原则,抽象不应该依赖于细节,而这种写法很明显违背了这种原则。

    下面看看使用工厂模式应该怎么去实现:

    代码案例

    编写专门的工厂类,再编写具体的工厂子类。在具体操作的 MainForm 中通过构造把子类对象传入。用多态的方式,避免了 MainForm 中的固定。

    // 抽象类
    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();
        }
    };
    
    // MainForm 没有具体类的依赖
    // 只有抽象的类的依赖
    // 把依赖具体类转移了
    class MainForm : public Form {
        SplitterFactory* factory;  // 含有工厂成员
    
    public:
        MainForm(SplitterFactory* factory) {
            this->factory = factory;
        }//想要实例化什么样的对象,由运行时决定
    
        void Button1_Click() {
            ISplitter* splitter = factory->CreateSplitter();  // 多态new
            splitter->split();
        }
    };
    
    • 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
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
  • 相关阅读:
    java项目-第92期基于ssm+shiro的物联及生产管理系统-java毕业设计
    26.cuBLAS开发指南中文版--cuBLAS中的Level-2函数syr()
    送给python初学者的福利!掌握了这些知识,你将超过80%的小白
    Tauri | 新版2.0路线图:更强大的插件以及支持 iOS、Android 应用构建
    代码规范问题,“static“ base class members should not be accessed via derived types
    螺旋矩阵、旋转矩阵、矩阵Z字打印
    基于SSM的邮箱客户端的设计与实现
    XTU-OJ 1191-Magic
    嵌入式系统在物联网中的应用和发展
    Python编程 print输出函数
  • 原文地址:https://blog.csdn.net/weixin_43717839/article/details/132602456