简单工厂模式

模拟一个简单的需求

设计一个简单的计算器,能够完成加减乘除的操作,并且能够设置运算的两个操作数(暂时不考虑计算器的界面)。

分析

思路1

可以创建一个计算器类,里面包含加减乘除的运算,以及设置获取操作数等操作,客户端直接创建一个计算器的对象,调用对应接口去执行运算。如果后续要添加新的运算,每次需要更改计算器类。

风险:由于新增操作每次要更改原来设计的类,可能会由于不小心改掉了原来的实现计算逻辑,从而导致原来正常运行的程序得不到正确的结果。

思路2

为每种运算单独设计一个类,客户端使用的时候可以根据不同的运算创建不同的对象,执行相应的操作。

由于每种运算符都有类似的操作,只是最终对数据执行的运算不一样,为了避免每个运算类写重复的代码,可以抽象出来一个运算类,包含公共的方法(设置操作数,获取操作数,获取计算结果等),具体运算类应该继承这个基类,在每个子类分别执行自己的运算。

此时,客户端需要使用运算器的时候,创建对象使用new的时候还是需要知道每个运算类的类名,若这些类分别在不同的头文件声明,使用这些类的时候还需要include一堆的头文件。如果要新增加运算符,上述的地方都要改动,很容易遗漏,非常的繁琐。

解决方案:由于创建的对象都是类似的对象(他们的父类都是同一个),可以创建一个类,提供一个静态方法,把创建具体类对象的工作都放到这个类中来完成,当客户端需要使用运算器的时候,就只需跟这个创建类打交道,并且使用这些对象的时候直接通过运算类的基类引用或者指针来执行操作就行了。当然,客户端和创建类需要使用一些通用的约定方式来表示要创建哪种类型的运算实例。针对本需求,可以直接使用加减乘数的字符来进行约定(“+”,“-”,“*”,“/”)。通过这个修改之后,就能够降低客户与每种运算类的耦合度。如果后续需要增加新的运算类,也不需要更改原来已经实现完好的各个具体的运算类,也就不会导致原来正常运行的结果由于不小心修改了原有代码导致结果不正确。

而上述所说的为了创建具体运算对象和增加的类,就是一个工厂类,解决方案就是简单工厂模式。

总结

简单工厂模式并不属于23种GOF设计模式之一。

简单工厂模式违背了面向对象设计中的开放封闭原则(简而言之,就是对扩展开放,对修改封闭)。按照上述的需求,需要增加一种运算,不妨就假设增加指数运算。此时需要增加一个指数运算类(这种是扩展操作,不修改原有实现,只要新增一个类,就是对扩展开放),还需要在工厂类中增加一种对象的创建逻辑(这种是修改操作,面向对象不提倡修改,就是对修改封闭),这样的修改还是会导致风险。

c++示例代码

头文件calculator.h,声明了抽象类运算类,以及具体的运算类,还有运算器工厂类

1 #ifndef __CALCULATOR_H__ 2 #define __CALCULATOR_H__ 3  4 //运算抽象类 5 class MyOperator 6 { 7 public: 8     MyOperator(char op, double A = 0.0, double B = 0.0) :m_op(op), m_numberA(A), m_numberB(B) {} 9     virtual ~MyOperator() {}10 11     //获取运算结果12     virtual double getResult()=0;13     //获取操作数14     double getNumA()const { return m_numberA; }15     double getNumB()const { return m_numberB; }16     //获取运算符17     char getOp()const { return m_op; }18     //设置操作数19     void setNumA(double A) { m_numberA = A; }20     void setNumB(double B) { m_numberB = B; }21 22 private:23     //运算符24     char m_op;25     //运算的两个操作数26     double m_numberA;27     double m_numberB;28 };29 30 //加法运算类:继承运算抽象类31 class OperatorPlus:public MyOperator32 {33 public:34     OperatorPlus(char op,double A = 0.0,double B = 0.0):MyOperator(op,A,B) {}35     virtual double getResult();36 };37 38 //减法运算类:继承运算抽象类39 class OperatorMinus :public MyOperator40 {41 public:42     OperatorMinus(char op,double A = 0.0, double B = 0.0) :MyOperator(op,A, B) {}43     virtual double getResult();44 };45 46 //乘法运算类:继承运算抽象类47 class OperatorMultiply :public MyOperator48 {49 public:50     OperatorMultiply(char op,double A = 0.0, double B = 0.0) :MyOperator(op,A, B) {}51     virtual double getResult();52 };53 54 //除法运算类:继承运算抽象类55 class OperatorDivision :public MyOperator56 {57 public:58     OperatorDivision(char op,double A = 0.0, double B = 0.0) :MyOperator(op,A, B) {}59     virtual double getResult();60 };61 62 //运算工厂类,用于生产客户端需要的具体类63 class OperatorFactory64 {65 public:66     static MyOperator* getOperator(char op,double A = 0.0,double B = 0.0);67 };68 #endif

实现文件calculator.cpp,生面声明的每个类的具体实现

1 #include <iostream> 2 #include "calculator.h" 3  4 using namespace std; 5  6 //加法运算 7 double OperatorPlus::getResult() 8 { 9     return (getNumA() + getNumB());10 }11 12 //减法运算13 double OperatorMinus::getResult()14 {15     return (getNumA()-getNumB());16 }17 18 //乘法运算19 double OperatorMultiply::getResult()20 {21     return (getNumA() * getNumB());22 }23 24 //除法运算25 double OperatorDivision::getResult()26 {27     double result = 0.0;28     if (0 == getNumB())29     {30         cout << "B not allow to be 0" << endl;31     }32     else33     {34         result = getNumA() / getNumB();35     }36     return result;37 }38 39 //运算工厂类,用于生产客户端需要的具体运算类40 MyOperator* OperatorFactory::getOperator(char opStr,double A,double B)41 {42     switch (opStr)43     {44     case '+':45         return new OperatorPlus(opStr, A, B);46     case '-':47         return new OperatorMinus(opStr, A, B);48     case '*':49         return new OperatorMultiply(opStr, A, B);50     case '/':51         return new OperatorDivision(opStr, A, B);52     default:53         cout << "NOT FOUND OPERATOR" << endl;54         return nullptr;55     }56 }

测试文件testCalculator.cpp,调用运算器类的客户端

1 #include "calculator.h" 2 #include <iostream> 3  4 using namespace std; 5  6 int main() 7 { 8     //声明一个指针数组,用于保存运算类对象 9     MyOperator* myOp[4];10 11     //获取一个加法类的对象12     myOp[0] = OperatorFactory::getOperator('+', 1.0, 2.0);13     //获取一个减法类的对象14     myOp[1] = OperatorFactory::getOperator('-', 1.0, 2.0);15     //获取一个乘法类的对象16     myOp[2] = OperatorFactory::getOperator('*', 1.0, 2.0);17     //获取一个除法类的对象18     myOp[3] = OperatorFactory::getOperator('/', 1.0, 2.0);19 20     //多态的运用,用基类指针指向每个子类的对象,并且获取计算结果getResult()21     MyOperator *p = myOp[0];22     for (int i = 0; i < 4; p = myOp[++i])23     {24         cout << p->getNumA() << p->getOp() << p->getNumB() << "=" << p->getResult() << endl;25         //用完就清理现场26         delete p;27         p = nullptr;28     }29     return 0;30 }

运行结果

(0)

相关推荐

  • 【从零学习OpenCV 4】Mat类支持的运算

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • java重要基础知识汇总

    Table of Contents 关于java语言设计理念 抽象类与接口的区别是什么 java为什么不支持多继承 java里的枚举实现机制是什么 java中的内部类 关于类Collections,A ...

  • 大神可以解释一下c语言里int,double,c,d,IF都是什么意思、在什么情况下用吗?

    我本人用C,C++比较多,回答一下你的提问. 首先,分一下类.int,double,这两个在c语言中表示变量类型:c,d,不能单独使用,与%一起,表示格式化输出的数据类型:至于IF,它不属于C语言的关 ...

  • 设计模式学习笔记 ———— 简单工厂模式

    # 背景 简单工厂模式是很多程序员学习的第一个设计模式,因为其不但原理简单而且易于上手,在日常工作的代码中也常有体现.今天分享一个基于实现"加"."减".&qu ...

  • 【6/25】使用简单工厂模式(Simple Factory Pattern)改写Page基类

    这是<小游戏从0到1设计模式重构>系列内容第6篇,所有源码及资料在"程序员LIYI"公号回复"小游戏从0到1"获取. 工厂模式有三个姐妹:简单工厂模 ...

  • PHP设计模式之简单工厂模式

    PHP设计模式之简单工厂模式 先从简单工厂入门,不管是面试还是被他人面试,在问到设计模式的时候,大多数人都会提到工厂模式.毫无疑问,工厂相关的几种模式在设计模式中是最出名的也是应用比较广泛的一种模式. ...

  • [PHP小课堂]PHP设计模式之简单工厂模式

    PHP设计模式之工厂方法模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 【C++设计模式一】C++简单工厂模式

    (1)定义 定义一个简单工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类. (2)结构 简单工厂模式有以下的结构: 工厂(Factory):根据客户提供的具体产品类的参数 ...

  • 【重温设计模式】之002简单工厂模式

    [重温设计模式系列源码] 简单工厂模式 基本原理 含义 简单工厂模式又叫静态方法模式(因为工厂类定义了一个静态方法). 在现实生活中,工厂是生产产品的, 同样的,在设计模式中,一个负责生产" ...

  • 【设计模式】简单工厂模式

    定义 通过工厂类提供的方法,创建不同的派生类 通常创建的类都具有共同的基类/接口 优缺点 优点 客户端与具体的实现类解耦 缺点 新增产品需要修改原来工厂类的方法,不符合开闭原则 角色 客户端 --&g ...

  • PHP设计模式—工厂模式之简单工厂模式

    定义: 简单工厂模式:将调用者和创建者分离,实现解耦,调用者直接向工厂请求,通过工厂去选择需要实例化的对象,用一个单独的类来做这个创建实例的过程. 代码实例: 问题:假设一个关于个人事务管理的项目中有 ...

  • 深入学习《大话设计模式》 简单工厂模式

    简单工厂模式 定义:封装改变,既然要封装改变,自然也就要找到需要更改的代码,然后将需要更改的代码用类来封装,这样的思路就是我们简单工厂模式的实现方式了 下面我们通过一则小故事来简述一下我们在项目中为什 ...

  • 大白话简单工厂模式 (Simple Factory Pattern)

    从买车经历说起 毕业两年,码农张小两口无法忍受挤公交,凌晨起床抢火车票的痛苦,遂计划买车.逛了多家4S店,最终定下日产某车型的轿车.4S店接受订单后,向工厂说明车型,工厂随后进行汽车制造,运输到4S店 ...