• 工厂方法(整理自李建忠<C++设计模式>视频)


    整理自李建忠<C++设计模式>视频:https://www.bilibili.com/video/BV1kW411P7KS?p=8

    一.导入:"对象创建"模式和工厂模式

    工厂模式只是该模式下的一种.

     二.举例说明

    有这样一个场景:需要在MainForm中设计一个按钮,这个按钮具有文件分割的功能,支持多种类型的文件分割,比如二进制,文本类型.

    不使用工厂模式的设计场景:

    MainForm.cpp:

     1 class MainForm
     2 {
     3 public:
     4     MainForm() {
     5     }
     6 
     7     void Btn1Click()
     8     {
    15         ISplit *splitter = new BinarySplit();
    16         splitter->SplitFunc();
    18     }
    19 };

    Split.hpp

     1 #pragma once
     2 #include"stdio.h"
     3 //抽象基类
     4 class ISplit
     5 {
     6 public:
     7     ISplit() {}
     8     virtual ~ISplit() {}
     9 
    10     virtual void SplitFunc() = 0;
    11 };
    12 
    13 //具体类
    14 class BinarySplit :public ISplit
    15 {
    16 public:
    17     void SplitFunc()
    18     {
    19         printf("This is BinarySplit
    ");
    20     }
    21 };
    22 
    23 class TxtSplit : public ISplit
    24 {
    25 public:
    26     void  SplitFunc()
    27     {
    28         printf("This is TxtSplit
    ");
    29     }
    30 };

    可以看到即便是Split.cpp中使用了多态的方法,在MainForm.cpp中的Btn1Click()还是会依赖于具体的类型,如果要实现别的类的切割函数,就需要在函数里添写,很不符合代码的复用性.

    引入工厂模式后的场景:

    Split.hpp保持不变

    增加SplitFactory.hpp文件

     1 #include"Split.hpp"
     2 //工厂基类
     3 class ISplitFactory
     4 {
     5     public:
     6         ISplitFactory() {
     7 
     8     }
     9         virtual ~ISplitFactory()
    10         {
    11 
    12     }
    13 
    14     virtual ISplit *CreateSplitter() = 0;
    15 };
    16 
    17 //具体工厂
    18 class BinarySplitFactory : public ISplitFactory
    19 {
    20     public:
    21         ISplit *CreateSplitter()
    22         {
    23             return new BinarySplit();
    24     }
    25 };
    26 
    27 class TxtSplitFactory : public ISplitFactory
    28 {
    29     public:
    30         ISplit *CreateSplitter()
    31         {
    32             return new TxtSplit();
    33     }
    34 };

    修改MainForm.cpp文件.

    #include"Split.hpp"
    #include"SplitFactory.hpp"
    
    class MainForm
    {
    public:
        ISplitFactory *splitFactory;
        MainForm(ISplitFactory *splitFactory) {
            this->splitFactory = splitFactory;
        }
    
        void Btn1Click()
        {
            ISplit *splitter = splitFactory->CreateSplitter();//通过工厂模式做成了"多态new"
            splitter->SplitFunc();
        }
    
    };

    这里增加的工厂基类同样定义了一个纯虚函数,用来创建Split对象,而实现的过程在子类中进行实现,这样的话就相当于延迟到子类.

    上面的情况在MainForm.cpp中通过接受传递过来的splitFactory来确定运行时应该执行谁的函数.在这种模式下,对具体类型的依赖被放到了外边(main.cpp这个调用方)了,而上述代码里面不再存在依赖.

    此时的main函数:

    int main()
    {
        ISplitFactory *splitFactory = new BinarySplitFactory();
        MainForm mf(splitFactory);
        mf.Btn1Click();
        return 0;
    }

    //注:这里没有考虑内存管理,正常应该在析构函数中delete掉堆上的内存

    工厂模式那里,有些朋友疑惑为啥不直接传ISplitter就好了,同样是从外部传参,何必那么麻烦另外写个工厂?我觉得是因为如果直接传ISplitter,那这个方法只能用到这么一个ISplitter,而工厂却可以“批量生产”,这就是工厂的优势

    --摘自https://www.bilibili.com/video/BV1kW411P7KS?p=8切切切Y的评论.

    三.结构总结

    红色的部分是稳定的,蓝色的部分是变化的.让MainForm依赖红色的.

     

    新战场:https://blog.csdn.net/Stephen___Qin
  • 相关阅读:
    用spring tool suite插件创建spring boot项目时报An internal error occurred during: "Building UI model". com/google/common/
    Eclipse卸载插件SpringSoource-tool-suite
    spring-tool-suite使用教程,并创建spring配置文件
    MySQL获取指定长度的字符串的函数left(s,n)和right(s,n)
    maven web项目配置log4j,及log4j参数设置
    Caused by: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'zoneId' in 'class java.lang.String'
    ifconfig 输出里没有IP地址
    maven web项目生成WebContent或WebRoot目录
    Window 命令行神器:cmder
    Filezilla Download for Linux (deb, rpm, txz, xz, amd64, i386, i486, i586, i686, x86_64)
  • 原文地址:https://www.cnblogs.com/Stephen-Qin/p/11604941.html
Copyright © 2020-2023  润新知