zoukankan      html  css  js  c++  java
  • 【设计模式】简单工厂模式

     

    计算器类为例,有加和减操作,提供给用户的接口只是操作符(加 或 减),两个操作数。

    首先有一个计算器抽象基类两个子类,分别为加类 和 减类,用户通过调用类工厂来计算结果,在类厂内部通过用户输入的操作符来实例化不同的操作类,并用多态性质,将子类的指针(或引用)赋值给抽象基类的指针(或引用),然后通过抽象基类的指针(或引用)来调用计算结果的虚函数,从而获得结果。

    NOTE:一般意义上的简单工厂模式一般用来根据输入来获得相应的动态类型( 父类指针 = 即去new不同的子类),然后赋值给父类指针(或引用),利用多态性质去调用计算结果的虚函数。 本文稍微修改了一下,类厂不再返回动态类型,而是在内部用一个成员变量来保存该动态类型,类厂内有一个计算结果的函数(不是虚函数),然后在该函数内去获得真正的动态类型,调用相应计算器类(及其子类)的虚函数计算结果。

     

    计算器类代码如下

     

    /************************************************************************
    设计模式1
    简单工厂模式
    类厂负责对象的创建,以计算器为例,类工厂提供给用户的接口只是操作符和两个操作数
    类长内部会根据操作符去实例化不同的类对象,然后用计算器的基类指针调用计算结果
    虚函数
    
    ************************************************************************/
    
    ///////////////计算 抽象基类/////////////////////////////////////////////
    class CCaculate
    {
    protected: 
        int m_nOpear1; //操作数1
           int m_nOpera2; //操作数2
    
    public:
        virtual int GetResult() = 0;         //计算结果
           CCaculate(int nOpera1, int nOpera2);
        virtual ~CCaculate();                //虚析构函数
    };
    
    CCaculate::CCaculate(int nOpera1, int nOpera2)
    {
        m_nOpear1 = nOpera1;
        m_nOpera2 = nOpera2;
    }
    
    CCaculate::~CCaculate()
    {
    
    }
    int CCaculate::GetResult()
    {
        return 0;
    }
    
    ///////////////加法类////////////////////////////////////////////////////
    class CAdd : public CCaculate  
    {
    public: 
        CAdd(int nOpera1, int nOpera2) : CCaculate(nOpera1, nOpera2){}
        virtual int GetResult();
        virtual ~CAdd();
    };
    
    int CAdd::GetResult()
    {
        return m_nOpear1 + m_nOpera2;
    }
    CAdd::~CAdd()
    {
    
    }
    //////////////减法类//////////////////////////////////////////////////////
    class CSub : public CCaculate
    {
    public:
        CSub(int nOpera1, int nOPera2) : CCaculate(nOpera1, nOPera2){};
        virtual int GetResult();
        virtual ~CSub(); 
    };
    
    CSub::~CSub(){}
    int CSub::GetResult()
    {
        return m_nOpear1 - m_nOpera2;
    }

    类厂代码如下

    ///////////////简单工厂////////////////////////////////////////////////////
    class FactoryCaculate
    {
    protected:
        char m_cOperation;  //操作符
          int  m_nOpera1;     //操作数1
          int  m_nOpera2;     //操作数2
          CCaculate* m_ptrCal;//计算类 抽象基类指针
    
    public: 
        FactoryCaculate(char operation, int nOpera1, int nOpera2);
        int GetResult();
        virtual ~FactoryCaculate();
    };
    
    FactoryCaculate::FactoryCaculate(char operation, int nOpera1, int nOpera2)
    {
        m_cOperation = operation;     
        m_nOpera1    = nOpera1;
        m_nOpera2    = nOpera2;
        m_ptrCal     = NULL;
    }
    
    //计算结果,简单工厂模式违背了开闭原则(对扩展开放,对修改关闭)
    //当有新的运算增加时,增加一个计算器抽象基类的子类的同时
    //还要修改GetResult()函数的switch case结构
    int FactoryCaculate::GetResult()
    {
        int nResult = 0;
     
        if (NULL != m_ptrCal) delete m_ptrCal;
    
        switch(m_cOperation)
        {
        case '+': m_ptrCal = new CAdd(m_nOpera1, m_nOpera2); 
            if(NULL != m_ptrCal) {nResult = m_ptrCal->GetResult();} break;
    
        case '-': m_ptrCal = new CSub(m_nOpera1, m_nOpera2); 
            if(NULL != m_ptrCal) {nResult = m_ptrCal->GetResult();} break;
        
        default:  break;
        }
    
        return nResult;
    }
    
    FactoryCaculate::~FactoryCaculate()
    {
        if (NULL != m_ptrCal) delete m_ptrCal;
        m_ptrCal = NULL;
    }

    main函数

    int _tmain(int argc, _TCHAR* argv[])
    {
        FactoryCaculate factCaculate1('+', 100, 200);
        cout << "Result is "<<factCaculate1.GetResult()<<endl;
    
        FactoryCaculate factCaculate2('-', 100, 1000);
        cout << "Result is "<<factCaculate2.GetResult()<<endl;
    
        FactoryCaculate factCaculate3('*', 100, 10);
        cout << "Result is "<<factCaculate3.GetResult()<<endl; 
    
    
        return 0;
    }

    运行结果

    简单工厂有个缺点:当有新的操作类(乘除)时,除了新增加CCaculate抽象基类的子类以外,还需要修改类厂的代码,修改switch...case代码,这违反了【开闭原则】即对扩展开放,对修改关闭。

    本文中的修工厂的修改不知道是好还是不好呢?

     

  • 相关阅读:
    一种flink 作业提交失败的情况描述与原因排查
    Linux中对管道命令中的任意子命令进行返回码校验
    优化算法与特征缩放
    优化算法
    mvn-dependencies-vs-dependencyManagement
    Caused by java.lang.Exception Failed to send data to Kafka Expiring
    学习ArrayList的扩容机制
    SpringBoot多数据源配置
    idea内存不足或过大闪退
    利用csv文件批量编辑更新sql
  • 原文地址:https://www.cnblogs.com/cuish/p/3719729.html
Copyright © 2011-2022 走看看