设计一个简单的计算器,可以完成加减乘除的操做,而且可以设置运算的两个操做数(暂时不考虑计算器的界面)。ios
能够建立一个计算器类,里面包含加减乘除的运算,以及设置获取操做数等操做,客户端直接建立一个计算器的对象,调用对应接口去执行运算。若是后续要添加新的运算,每次须要更改计算器类。c++
风险:因为新增操做每次要更改原来设计的类,可能会因为不当心改掉了原来的实现计算逻辑,从而致使原来正常运行的程序得不到正确的结果。设计模式
为每种运算单独设计一个类,客户端使用的时候能够根据不一样的运算建立不一样的对象,执行相应的操做。数组
因为每种运算符都有相似的操做,只是最终对数据执行的运算不同,为了不每一个运算类写重复的代码,能够抽象出来一个运算类,包含公共的方法(设置操做数,获取操做数,获取计算结果等),具体运算类应该继承这个基类,在每一个基类分别执行本身的运算。测试
此时,客户端须要使用运算器的时候,建立对象使用new的时候仍是须要知道每一个运算类的类名,若这些类分别在不一样的头文件声明,使用这些类的时候还须要include一堆的头文件。若是要新增长运算符,上述的地方都要改动,很容易遗漏,很是的繁琐。spa
解决方案:因为建立的对象都是相似的对象(他们的父类都是同一个),能够建立一个类,提供一个静态方法,把建立具体类对象的工做都放到这个类中来完成,当客户端须要使用运算器的时候,就只需跟这个建立类打交道,而且使用这些对象的时候直接经过运算类的基类引用或者指针来执行操做就好了。固然,客户端和建立类须要使用一些通用的约定方式来表示要建立哪一种类型的运算实例。针对本需求,能够直接使用加减乘数的字符来进行约定(“+”,“-”,“*”,“/”)。经过这个修改以后,就可以下降客户与每种运算类的耦合度。若是后续须要增长新的运算类,也不须要更改原来已经实现无缺的各个具体的运算类,也就不会致使原来正常运行的结果因为不当心修改了原有代码致使结果不正确。设计
而上述所说的为了建立具体运算对象和增长的类,就是一个工厂类,解决方案就是简单工厂模式。指针
简单工厂模式并不属于23种GOF设计模式之一。code
简单工厂模式违背了面向对象设计中的开放封闭原则(简而言之,就是对扩展开放,对修改封闭)。按照上述的需求,须要增长一种运算,不妨就假设增长指数运算。此时须要增长一个指数运算类(这种是扩展操做,不修改原有实现,只要新增一个类,就是对扩展开放),还须要在工厂类中增长一种对象的建立逻辑(这种是修改操做,面向对象不提倡修改,就是对修改封闭),这样的修改仍是会致使风险。对象
头文件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 MyOperator 32 { 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 MyOperator 40 { 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 MyOperator 48 { 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 MyOperator 56 { 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 OperatorFactory 64 { 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 else 33 { 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 }
运行结果