【学习笔记】C++下的简单工厂模式(程杰-大话设计模式)

引入:利用C++、Java、C#或VB.NET任意一种面向对象语言实现一个计算器控制程序,要求输入两个数和运算符号,得到结果。


一、最粗糙实现版本(Calculator01):

#include<iostream>
#include<string>

using namespace std;

int main()
{
	cout << "Please enter the first number:" << endl;
	double firstNumber;
	cin >> firstNumber;
	cout << "Please enter the Second number:" << endl;
	double secondNumber;
	cin >> secondNumber;
	cout << "Please select calculation method:  \'+ - * / \'" << endl;
	string method;
	cin >> method;

	if (method == "+")
	{
		cout << firstNumber + secondNumber << endl;
	}

	if (method == "-")
	{
		cout << firstNumber - secondNumber << endl;
	}

	if (method == "*")
	{
		cout << firstNumber * secondNumber << endl;
	}

	if (method == "/")
	{
		cout << firstNumber / secondNumber << endl;
	}
	system("pause");
	return 0;
}

看似可以实现功能,但是存在以下问题:

1.多次使用if分支判断,让计算机做无用的判断;

2.如果输入了0的除数,或者输入了字符符号而不是数字,程序会出错。


二、针对上述问题改进版(Calculator02):

#include<iostream>
#include<string>

using namespace std;

int main()
{
	cout << "Please enter the first number:" << endl;
	double firstNumber;
	cin >> firstNumber;
	cout << "Please enter the Second number:" << endl;
	double secondNumber;
	cin >> secondNumber;
	cout << "Please select calculation method:  \'+ - * / \'" << endl;
	char method;
	cin >> method;

	switch (method)
	{
	case '+':
		cout << firstNumber + secondNumber << endl;
		break;
	case '-':
		cout << firstNumber - secondNumber << endl;
		break;
	case '*':
		cout << firstNumber * secondNumber << endl;
		break;
	case '/':
		if (secondNumber != 0)
		{
			cout << firstNumber / secondNumber << endl;
			break;
		}
		else
		{
			cout << "Divisor cannot be 0." << endl;
			break;
		}
	default:
		break;
	}
	system("pause");

	return 0;
}

目前,虽然可以实现计算器的功能。但是没有用到面向对象的思想,只是一股脑在main函数中把所有的功能进行堆砌。代码复用性低。


三、类封装后的计算器(Calculator03):

将业务逻辑与界面逻辑分开,降低之间的耦合度。将计算器类进行封装。

#include<iostream>

using namespace std;

class Calculator
{
public:
	Calculator() = default;
	~Calculator() = default;
	void getResult(double firstNum, double secondNum, char method)
	{
		switch (method)
		{
		case '+':
			cout << firstNum + secondNum << endl;
			break;
		case '-':
			cout << firstNum - secondNum << endl;
			break;
		case '*':
			cout << firstNum * secondNum << endl;
			break;
		case '/':
			if (secondNum != 0)
			{
				cout << firstNum / secondNum << endl;
				break;
			}
			else
			{
				cout << "Divisor cannot be 0." << endl;
				break;
			}
		default:
			break;
		}
	}

};

int main()
{

	cout << "Please enter the first number:" << endl;
	double firstNumber;
	cin >> firstNumber;
	cout << "Please enter the Second number:" << endl;
	double secondNumber;
	cin >> secondNumber;
	cout << "Please select calculation method:  \'+ - * / \'" << endl;
	char method;
	cin >> method;

	Calculator c;
	c.getResult(firstNumber, secondNumber, method);

	system("pause");
	
	return 0;
}

现在,完成了计算器类的封装。但是如果需要增加一种新的运算方法,就需要对Switch分支进行增删、修改。若是复杂的程序,大量的修改可能会产生错误。因此继续使用继承来优化计算器程序。


四、颗粒度更细的计算器(Calculator04):

#include<iostream>

using namespace std;

class AbsCalculator
{
public:
	AbsCalculator() = default;
	~AbsCalculator() = default;
	
	virtual void calculateMethod(double firstnum, double secondNum){};

	void setFirstNum(double firstNum)
	{
		this->firstNum = firstNum;
	}
	double getFirstNum()
	{
		return this->firstNum;
	}

	void setSecondNum(double secondNum)
	{
		this->secondNum = secondNum;
	}
	double getSecondNum()
	{
		return this->secondNum;
	}
private:
	double firstNum;
	double secondNum;
};

class addCalculator : public AbsCalculator
{
public:
	void calculateMethod(double firstNum, double secondNum)
	{
		cout << firstNum + secondNum << endl;
	}
};

class subCalculator : public AbsCalculator
{
public:
	void calculateMethod(double firstNum, double secondNum)
	{
		cout << firstNum - secondNum << endl;
	}
};

class multiCalculator : public AbsCalculator
{
public:
	void calculateMethod(double firstNum, double secondNum)
	{
		cout << firstNum * secondNum << endl;
	}
};

class divCalculator : public AbsCalculator
{
public:
	void calculateMethod(double firstNum, double secondNum)
	{
		if (secondNum != 0)
		{
			cout << firstNum / secondNum << endl;
		}
		else
		{
			cout << "Divisor cannot be 0." << endl;
		}
	}
};

定义一个抽象的计算器类,它拥有一个虚的计算方法,需要在子类中重写。

子类分别定义为加法计算器、乘法计算器、减法计算、除法计算器,继承抽象的计算器类。再分别实现对应的计算方法。

那么如何才能调用对应功能的计算器呢(如何实例化对象)?


五、通过简单工厂类来实例化对象:

#include<iostream>
#include<string>

using namespace std;

//class AbsCalculator;
//class addCalculator;
//class subCalculator;
//class multiCalculator;
//class divCalculator;

class AbsCalculator
{
public:
	AbsCalculator() = default;
	~AbsCalculator() = default;

	virtual void calculateMethod(double firstnum, double secondNum) {};

	void setFirstNum(double firstNum)
	{
		this->firstNum = firstNum;
	}
	double getFirstNum()
	{
		return this->firstNum;
	}

	void setSecondNum(double secondNum)
	{
		this->secondNum = secondNum;
	}
	double getSecondNum()
	{
		return this->secondNum;
	}
private:
	double firstNum;
	double secondNum;
};

class addCalculator : public AbsCalculator
{
public:
	void calculateMethod(double firstNum, double secondNum)
	{
		cout << firstNum + secondNum << endl;
	}
};

class subCalculator : public AbsCalculator
{
public:
	void calculateMethod(double firstNum, double secondNum)
	{
		cout << firstNum - secondNum << endl;
	}
};

class multiCalculator : public AbsCalculator
{
public:
	void calculateMethod(double firstNum, double secondNum)
	{
		cout << firstNum * secondNum << endl;
	}
};

class divCalculator : public AbsCalculator
{
public:
	void calculateMethod(double firstNum, double secondNum)
	{
		if (secondNum != 0)
		{
			cout << firstNum / secondNum << endl;
		}
		else
		{
			cout << "Divisor cannot be 0." << endl;
		}
	}
};

class CalculatorFactory // 为什么使用前置声明不行?
{
public:
	AbsCalculator* calculator;
	// 根据不同的方法,“生产”不同的计算器
	AbsCalculator* productCalculator(char method)
	{
		switch (method)
		{
		case '+':
			calculator = new addCalculator;
			break;
		case '-':
			calculator = new subCalculator;
			break;
		case '*':
			calculator = new multiCalculator;
			break;
		case '/':
			calculator = new divCalculator;
			break;
		default:
			break;
		}
		return calculator; // 遗忘返回值
	}
};

void test()
{
	cout << "Please enter the first number:" << endl;
	double firstNumber;
	cin >> firstNumber;
	cout << "Please enter the Second number:" << endl;
	double secondNumber;
	cin >> secondNumber;
	cout << "Please select calculation method:  \'+ - * / \'" << endl;
	char method;
	cin >> method;

	AbsCalculator* calculator;
	CalculatorFactory calFactory;

	
	calculator = calFactory.productCalculator(method);
	calculator->setFirstNum(firstNumber);
	calculator->setSecondNum(secondNumber);
	calculator->calculateMethod(calculator->getFirstNum(), calculator->getSecondNum());
}

int main()
{
	int i = 0;
	while (i < 5)
	{
		test();
		i++;
	}
	system("pause");
	return 0;
}

通过输入不同的运算符号,工厂类就能产生不同类型的计算器,就像工厂根据不同的生产订单来生产产品。

但是我也遇到一些问题,比如将工厂类定义在最初的位置,使用前置声明。仍然告诉我:[c2027] 使用了未定义类型。

参考资料:《大话设计模式》,作者:程杰

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值