• C++简单工厂模式详解


    1.问题引入

    编写一个计算器程序代码,可使用任意一种面向对象语言编写。

    2.编写代码思路的迭代

    2.1 main函数主体内编写全部代码

    在main函数主题写好了全部逻辑。包括两个运算数字的获取,中间运算符号的获取,通过对符号的if分支判断选取运算符参与运算数字的运算。这个时候出现的问题有:1.命名不规范。很多变量名都是A,B,C,不能通过名字知晓含义。2.if分支判断做了三次无用功,在这里可以选用switch。3.除法没有考虑除0判断,程序的健壮性不够。之后进行了第一次修改。

    2.2 修改上述问题后的main函数代码

    修改上诉问题后代码是没问题的,但是问题是不符合出题人心意。当前代码由于全部都在main函数里面,程序不容易维护,不容易拓展,不容易复用,不够灵活。
    软件可维护性指的是维护人员对该软件进行维护的难易程度,具体包括理解、改正、改动和改进该软件的难易程度。
    软件的可扩展性表现为基础设置不需要经常变更,应用之间较少依赖或耦合,可以对需求变更快速响应。
    软件复用是使用已有的软件组件去实现或更新软件系统的过程。
    软件开发中的灵活性通常是指管理方法和开发方法的灵活性,更细微的范围内则是指编码的灵活性。如果在解决某一问题时具备了多种可选择的方法,则可以认为开发过程拥有灵活性。
    故接下来进行第二次修改。

    2.3 引入面向对象后的代码

    代码分为两部分,一部分是关于operation类的编写,包含了两个成员变量及计算的成员方法。另一个部分是主函数的编写。这样的好处是实现了业务和界面的分离。缺点是这里只用了封装,没有用到面向对象中的继承和多态。假如要新加一个开根号的运算(假设这里它只有加减乘除的运算),那么需要拿到所有方法代码再进行修改,但其实感觉上而言都是奇怪的操作,因为只想新加一个功能却需要拿到所有功能的代码才能进行添加。其实归根结底就是耦合度太高。
    耦合度是某模块(类)与其它模块(类)之间的关联、感知和依赖的程度,是衡量代码独立性的一个指标,也是软件工程设计及编码质量评价的一个标准。
    故接下来进行第三次修改。

    2.4 加上继承和多态后的代码

    在上一步,operation是作为主类,但是由于耦合度太高,所以做进一步耦合度的降低,采用继承和多态。所以有关于计算的四个类operationAdd、operationSub、operationMul、operationDiv继承operation,并且在operation中有虚方法getResult,子类里面都对该方法进行重写,从而实现多态。
    那么其实就剩一个问题:就是实例化对象,比如增加开根号运算,那么我们应该考虑用一个类单独去制造出对象,这就是简单工厂模式。

    3.C++简单工厂代码

    //simpleFactory.h
    #ifndef _SimpleFactory_H_
    #define _SimpleFactory_H_
    
    #include 
    #include 
    #include 
    
    using namespace std;
    
    class Operation{
        protected:
            double _numberA = 0;
            double _numberB = 0;
        public:
            Operation(){}
            Operation(double a, double b){
                _numberA = a;
                _numberB = b;
            }
            Operation &operator=(Operation &p){
                _numberA = p.getNumberA();
                _numberB = p.getNumberB();
            }
            double getNumberA(){
                return _numberA;
            }
            void setNumberA(double value){
                _numberA = value;
            }
            double getNumberB(){
                return _numberB;
            }
            void setNumberB(double value){
                _numberB = value;
            }
            virtual double GetResult(){
                return 0;
            }
    };
    class OperationAdd:public Operation{
        double GetResult(){
            double result = 0;
            result = _numberA + _numberB;
            return result;
        }
    };
    class OperationSub:public Operation{
        double GetResult(){
            double result = 0;
            result = _numberA - _numberB;
            return result;
        }
    };
    class OperationMul:public Operation{
        double GetResult(){
            double result = 0;
            result = _numberA * _numberB;
            return result;
        }
    };
    class OperationDiv:public Operation{
        double GetResult(){
            double result = 0;
            try{
                result = _numberA / _numberB;
            }catch(exception &){
                cout << "发生除0异常" << endl;
            }
            return result;
        }
    };
    class OperationFactory{
        public:
            static Operation* createOperation(char operate){
                Operation* oper;
                switch (operate){
                    case '+':
                        oper = new OperationAdd();
                        break;
                    case '-':
                        oper = new OperationSub();
                        break;
                    case '*':
                        oper = new OperationMul();
                        break;
                    case '/':
                        oper = new OperationDiv();
                        break;
                }
                return oper;
            }
    };
    #endif //_SimpleFactory_H_
    
    • 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
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    //simpleFactory.cpp
    #include "simpleFactory.h"
    
    int main(){
        Operation* oper;
        oper = OperationFactory::createOperation('+');
        oper->setNumberA(1);
        oper->setNumberB(2);
        double result = oper->GetResult();
        std::cout << "Result: " << result << std::endl;
        return 0;
    }
    //CSDN@Credic1017
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4.总结

    4.1 简单工厂模式适用场景

    在这里插入图片描述

    可以发现,简单工厂类是制造运算类的对象的,并且只需要传递关键参数给简单工厂类的方法(通常为静态方法),就可以创造出相应的对象出来。
    故简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象不需要关心。

    4.2收获

    1.可以通过封装、继承、多态把程序的耦合度降低。
    2.可以通过设计模式使程序变得更加灵活,易于修改,并且易于复用。
    3.简单工厂模式适用创建对象少的情况,需要传参来指定需要的对象(产品)。

    参考:《大话设计模式

  • 相关阅读:
    Linux-组管理和权限管理
    一个闲鱼挂机项目,让淘宝用户彻底“躺赢”
    【管理运筹学】第 9 章 | 网络计划(2,时间参数的计算 —— 工作的时间参数)
    计算机网络知多少面试---第2篇
    [Ext JS]图片显示方式
    elementUI 年份范围选择器实现
    【ESP32 + Edge Impulse平台】模拟多传感器数据融合实验测试
    ubuntu安装docker
    dreamweaver郑州旅游网页设计制作 简单静态HTML网页作品 我的家乡网页作业成品 学生旅游网站模板
    Kubernetes(k8s)访问控制:身份认证
  • 原文地址:https://blog.csdn.net/qq_43847153/article/details/127884448