面向对象编程:
所有初学者可能会有这个问题,在碰到问题就直觉地用计算机能够理解的逻辑来描述和表达待解决的问题及具体的求解过程。这种用计算机方式思考,本身没有什么问题,但是仅仅实现了当前的需求,程序不容易维护,不容易扩展,更不容易复用。达不到高质量代码的要求。
面向对象设计思想是通过封装、继承、多态把程序的耦合度降低。设计模式使得程序更加的灵活,容易修改,并且易于复用。
要求:
实现一个计算机控制台程序,要求输入两个数和运算符,得到结果。
简单实现1:
#include<iostream>
#include<istream>
#include<string>
using namespace std;
void Program()
{
std::cout << "请输入数字A: " << std::endl;
string A; // A命名非常不规范,无法明确表述准确的意思
getline(cin, A);
std::cout << "请选择运算符号(+、-、*、/): " << std::endl;
string C;
getline(cin, C);
std::cout << "请输入数字B: " << std::endl;
string B;
getline(cin, B);
// 判断分支,这种写法意味着每一个条件都要做判断,等于计算机做了三次无用功
double D;
if (C == "+")
D = std::stod(A) + std::stod(B);
else if (C == "-")
D = std::stod(A) - std::stod(B);
else if (C == "*")
D = std::stod(A) * std::stod(B);
else if (C == "/") // 如果除数中,当B为0时将产生异常导致程序崩溃
D = std::stod(A) / std::stod(B);
std::cout << "结果result = : " << D << std::endl;
}
int main()
{
Program();
system("pause");
return 0;
}
实现1的缺陷已经在代码中标出,需要做优化处理。
实现2:
#include<iostream>
#include<istream>
#include<string>
using namespace std;
void Program()
{
try
{
std::cout << "请输入数字A: " << std::endl;
string strNumberA;
getline(cin, strNumberA);
std::cout << "请选择运算符号(+、-、*、/): " << std::endl;
string C;
getline(cin, C);
std::cout << "请输入数字B: " << std::endl;
string strNumberB;
getline(cin, strNumberB);
double strNumberD;
if (C == "+")
strNumberD = std::stod(strNumberA) + std::stod(strNumberB);
else if (C == "-")
strNumberD = std::stod(strNumberA) - std::stod(strNumberB);
else if (C == "*")
strNumberD = std::stod(strNumberA) * std::stod(strNumberB);
else if (C == "/")
{
if (std::stod(strNumberB) == 0)
{
std::cout << "输入的数字B不能为0!" << std::endl;
return;
}
strNumberD = std::stod(strNumberA) / std::stod(strNumberB);
}
else
{
std::cout << "输入运算符号不在(+、-、*、/)之间!" << std::endl;
return;
}
std::cout << "结果result = : " << strNumberD << std::endl;
}
catch (const std::exception& ex)
{
std::cout << "您输入的内容有错: " << ex.what() << std::endl;
}
}
int main()
{
while (true)
{
std::cout << "--------------------------------------" << std::endl;
Program();
std::cout << "======================================" << std::endl;
std::cout << std::endl;
}
system("pause");
return 0;
}
实现2在实现和异常处理基本没有问题,但是并没有实现面向对象。
实现3:
如何能够让上述程序更加灵活并且易于复用,准确的说就是让业务逻辑与界面逻辑分开,让它们之间的耦合度下降。只有分开,才可以达到容易维护或扩展。
简单工厂模式设计如下:
操作分为加减乘除,因此可以抽象出一个运算类,分出加法类、减法类、乘法类和除法类,通过这四个类继承运算类。运算类关联简单工厂类,通过简单工厂类创建不同的操作对象。
#include<iostream>
#include<istream>
#include<string>
#include<map>
using namespace std;
enum NumOperate
{
Add = 1,
Sub = 2,
Mul = 3,
Div = 4
};
std::map<std::string, uint16_t> map_operate
{
{"+", NumOperate::Add},
{"-", NumOperate::Sub},
{"*", NumOperate::Mul},
{"/", NumOperate::Div}
};
class Operation
{
public:
virtual double GetResult()
{
return 0;
}
void SetNumberA(double A)
{
NumberA = A;
}
void SetNumberB(double B)
{
NumberB = B;
}
public:
double NumberA;
double NumberB;
};
class OperationAdd : public Operation
{
public:
double GetResult() override
{
double result = 0;
result = NumberA + NumberB;
return result;
}
};
class OperationSub : public Operation
{
public:
double GetResult() override
{
double result = 0;
result = NumberA - NumberB;
return result;
}
};
class OperationMul : public Operation
{
public:
double GetResult() override
{
double result = 0;
result = NumberA * NumberB;
return result;
}
};
class OperationDiv : public Operation
{
public:
double GetResult() override
{
double result = 0;
if (0 == NumberB)
{
std::cout << "除数不能为0! " << std::endl;
return 0;
}
result = NumberA / NumberB;
return result;
}
};
class OperationFactory
{
public:
Operation* CreateOperate(string operate)
{
Operation* oper = nullptr;
switch (map_operate[operate])
{
case Add:
oper = new OperationAdd();
break;
case Sub:
oper = new OperationSub();
break;
case Mul:
oper = new OperationMul();
break;
case Div:
oper = new OperationDiv();
break;
default:
std::cout << "输入运算符号不在(+、-、*、/)之间!" << std::endl;
break;
}
return oper;
}
};
int main()
{
OperationFactory* oper_factory = new OperationFactory();
auto oper_add = oper_factory->CreateOperate("+");
oper_add->SetNumberA(12);
oper_add->SetNumberB(23);
std::cout << "The result is: " << oper_add->GetResult() << std::endl;
system("pause");
return 0;
}