之前项目中有接触过设计模式,当时觉得无所谓,反正代码不都那样,随便写写实现就好。不需要什么设计模式这么虚的东西,后面水平渐长,才知存在即有理。所以重新开始整理下设计模式。
参考书籍《大话设计模式》。使用IDE VS2022 Unicode环境。
简单工厂
来看一道简单的面试题:请用C++这门面向对象语言实现一个简单的计算器控制台程序,要求输入两个数和运算符号,输出结果。
其实这个题很简单,有兴趣的同学可以先自己实现下,后面代码做下对比。
**友情提示:面向对象**。
这边我先写我的实现:
运算类:
class Operator
{
public:
virtual double GetResult() { return 0; };
double GetFirstNumber()
{
return m_dbFirstNumber;
}
void SetFirstNumber(const double value)
{
m_dbFirstNumber = value;
}
double GetSecondNumber()
{
return m_dnSecondNumber;
}
void SetSecondNumber(const double value)
{
m_dnSecondNumber = value;
}
private:
double m_dbFirstNumber;
double m_dnSecondNumber;
};
这里类成员函数我就在这里实现了,源代码我是在cpp文件中实现的,一般项目中也是应该在cpp文件中实现
加法类:
class Addition :public Operator
{
public:
double GetResult()
{
return GetFirstNumber() + GetSecondNumber();
};
};
减法类:
class Subtraction :public Operator
{
public:
double GetResult()
{
return GetFirstNumber() - GetSecondNumber();
};
};
乘法类:
class Multiplication :public Operator
{
public:
double GetResult()
{
return GetFirstNumber() * GetSecondNumber();
};
};
除法类:
class Division :public Operator
{
public:
double GetResult()
{
double result = 0;
double temp = GetSecondNumber();
if (temp)
{
result = GetFirstNumber() * 1.0 / GetSecondNumber();
}
else
{
AfxMessageBox(_T("除数不能为0!"));
}
return result;
};
};
工厂类:
.h文件:
#include"Operator.h"//运算类
#include <afxstr.h>
#include <memory>
class Factory
{
public:
std::unique_ptr<Operator> createOperate(const char* calculateType);
};
.cpp文件
int toUnicode(const char* str)
{
return str[0] + (str[1] ? toUnicode(str + 1) : 0);
}
constexpr inline int U(const char* str)
{
return str[0] + (str[1] ? U(str + 1) : 0);
}
std::unique_ptr<Operator> Factory::createOperate(const char* calculateType)
{
Operator* ptr = NULL;
switch (toUnicode(calculateType))
{
case U("+"):
ptr = new Addition();
break;
case U("-"):
ptr = new Subtraction();
break;
case U("*"):
ptr = new Multiplication();
break;
case U("/"):
ptr = new Division();
break;
default:
AfxMessageBox(_T("未知运算符!"));
break;
}
return (std::unique_ptr<Operator>)ptr;
}
这里有个问题是switch是不能用字符来进行判断的,所以进行了一定变换。这块我明天整理一下再重新说明下。
客户端实现:
void CCalculateDlg::OnBnClickedCalculate()
{
UpdateData(TRUE);
/*std::string a = CW2A(m_CalculateType);
const char* as = a.c_str();*/
std::string s = CT2A(m_CalculateType);
const char* cs = s.c_str();
std::unique_ptr<Operator> calculate = Fact.createOperate(cs);
if (calculate)
{
calculate->SetFirstNumber(m_FirstNumber);
calculate->SetSecondNumber(m_SecondNumber);
m_Result = calculate->GetResult();
}
UpdateData(FALSE);
}
运行界面1:
计算结果1:
运行界面2:
计算结果2:
综上,简单工厂模式可以让客户端和具体实现分开,具有低耦合;对于维护性和可扩展性也有了很大的提升。在项目中我们经常可以看到它的身影。
希望对你有所帮助~