天天看點

大話設計模式 —— 第一章《簡單工廠模式》C++代碼實作

簡介

 簡單工廠模式(Simple Factory Pattern)屬于類的建立型模式(但是簡單工廠模式不屬于23種設計模式之一),又叫靜态工廠方法模式(Static FactoryMethod Pattern), 是通過專門定義一個類來負責建立其他類的執行個體,這個類可以根據不同變量傳回不同類的産品執行個體。被建立的執行個體通常都具有共同的基類。

大話設計模式 —— 第一章《簡單工廠模式》C++代碼實作

ProductA、ProductB 和 ProductC 繼承自Product抽象類,Show方法是不同産品的自描述;Factory依賴于ProductA、ProductB和ProductC。 Factory根據不同的條件 建立不同的Product 對象。

  • 抽象(Product)産品:簡單工廠模式所建立的所有對象的父類,注意:這裡的父類可以是接口也可以是抽象類,它負責描述所有執行個體所共有的公共接口。
  • 具體産品(Concrete Product):簡單工廠所建立的具體執行個體對象,這些具體的産品往往都擁有共同的父類。
  • 工廠角色(Creator):這是簡單工廠模式的核心,由它負責建立所有的類的内部邏輯。當然工廠類必須能夠被外界調用,建立所需要的産品對象。

對于工廠模式,具體上可以分為三類:

  • 簡單工廠模式;
  • 工廠方法模式;
  • 抽象工廠模式。

工廠模式有一種非常形象的描述,建立對象的類就如一個工廠,而需要被建立的對象就是一個個産品;在工廠中加工産品,使用産品的人,不用在乎産品是如何生産出來的。從軟體開發的角度來說,這樣就有效的降低了子產品之間的耦合。

簡單工廠模式深入分析:

簡單工廠模式解決的問題是:
  • 如何去執行個體化一個合适的對象。
簡單工廠模式的核心思想就是:
  • 有一個專門的類來負責建立執行個體的過程。
具體來說,把産品看着是一系列的類的集合,這些類是由某個抽象類或者接口派生出來的一個對象樹。而工廠類用來産生一個合适的對象來滿足客戶的要求。

如果簡單工廠模式所涉及到的具體産品之間沒有共同的邏輯,那麼我們就可以使用接口來扮演抽象産品的角色;

如果具體産品之間有功能的邏輯,我們就必須把這些共同的東西提取出來,放在一個抽象類中,然後讓具體産品繼承抽象類。為實作更好複用的目的,共同的東西總是應該抽象出來的。

适用場合:

在程式中,需要建立的對象很多,導緻對象的new操作多且很複雜時,需要使用簡單工廠模式;

● 由于對象的建立過程是我們不需要去關心的,而我們注重的是對象的實際操作,是以,我們需要分離對象的建立和操作兩部分,如此,友善後期的程式擴充和維護。

代碼實作為:

#include<iostream>
using namespace std;

class Operation  //抽象運算類
{
public:
	
	double getA()
	{
		return m_numberA;
	}
	void setA(double value)
	{
		m_numberA = value;
	}


	double getB()
	{
		return m_numberB;
	}
	void setB(double value)
	{
		m_numberB = value;
	}

	virtual double getResult() = 0;
	
	virtual ~Operation() = default;
protected:
	Operation() {}
	double m_numberA = 0;
	double m_numberB = 0;
};

class OperationAdd : public Operation  //加法類,繼承運算類
{
public:
	double getResult()override
	{
		double result = m_numberA + m_numberB;
		return result;
	}
};

class OperationSub : public Operation  //減法類,繼承運算類
{
public:
	double getResult()override
	{
		double result = m_numberA - m_numberB;
		return result;
	}
};

class OperationMul : public Operation  //乘法類,繼承運算類
{
public:
	
	double getResult()override
	{
		double result = m_numberA * m_numberB;
		return result;
	}
};

class OperationDiv : public Operation  //除法類,繼承運算類
{
public:
	double getResult()override
	{
		double result = 0;
		if (m_numberB != 0)
		{
			 result = m_numberA / m_numberB;
		}
		else
		{
			return -1;
		}
		return result;
	}
};

class OperationFactory  //工廠類    
{
public:
	static Operation *createOperation(char type)
	{
		Operation *operation = nullptr;
		switch (type)
		{
		case '+':
			operation = new OperationAdd;
			break;
		case '-':
			operation = new OperationSub;
			break;
		case '*':
			operation = new OperationMul;
			break;
		case '/':
			operation = new OperationDiv;
			break;
		}
		return operation;
	}
};

int main()
{


	while (true)
	{
		cout << "\n請輸入第一個數進行計算:";
		double strNumberA;
		cin >> strNumberA;

		cout << "\n請先輸入四則運算符号,進行相應的運算(+、-、*、/):\n" << endl;
		char SignOfOperation = ' ';
		while (cin >> SignOfOperation)
		{
			if (SignOfOperation == '+' || SignOfOperation == '-' || SignOfOperation == '*' || SignOfOperation == '/')
			{
				break;
			}
			else
			{
				cout << "請輸入正确運算符号,否則無法進行計算,請重新輸入:";
				continue;
			}
		}

		cout << "請輸入第二個數進行計算:";
		double strNumberB;
		cin >> strNumberB;

		{
			cout << "\n*************************************************************" << endl
				<< "********************   電腦基本功能展示.   **********************" << endl
				<< "*****************************************************************" << endl
				<< "********************   選擇1——進行加法.   **********************" << endl
				<< "********************   選擇2——進行減法.   **********************" << endl
				<< "********************   選擇3——進行乘法.   **********************" << endl
				<< "********************   選擇4——進行除法.   **********************" << endl
				<< "********************   選擇5——清屏.   **********************" << endl
				<< "********************   選擇0——退出程式!   **********************" << endl
				<< "*****************************************************************" << endl;
		}
	

		cout << "\n********************   請輸入你想要使用的電腦的序号   ***************" << endl;
		cout << "請輸入你的選擇:";
		int userChoice(0);

		if (cin >> userChoice && userChoice == 0)
		{
			cout << "程式已退出,感謝您的使用!" << "\n" << endl;
			break;
		}
		Operation* oper = nullptr;
		
		switch (userChoice)
		{
		case 1:
			oper = OperationFactory::createOperation(SignOfOperation);
			oper->setA(strNumberA);
			oper->setB(strNumberB);
			cout << strNumberA << "+" << strNumberB << "=" << (oper->getResult()) << endl;
			break;

		case 2:
			oper = OperationFactory::createOperation(SignOfOperation);
			oper->setA(strNumberA);
			oper->setB(strNumberB);
			cout << strNumberA << "-" << strNumberB << "=" << (oper->getResult()) << endl;
			break;
		case 3:
			oper = OperationFactory::createOperation(SignOfOperation);
			oper->setA(strNumberA);
			oper->setB(strNumberB);
			cout << strNumberA << "*" << strNumberB << "=" << (oper->getResult()) << endl;
			break;

		case 4:
		{
			oper = OperationFactory::createOperation(SignOfOperation);
			oper->setA(strNumberA);
			oper->setB(strNumberB);
			if (double temp = oper->getResult())
			{
				cout << strNumberA << "/" << strNumberB << "=" << temp << endl;
			}
			else
			{
				cout << "錯誤,除數不能為0!" << endl;
			}
			break;
		}
		case 5:
			system("cls");
			cout << "螢幕已經清屏,可以重新輸入!" << "\n" << endl;
			break;
		default:
			cout << "輸入的序号不正确,請重新輸入!" << "\n" << endl;
		}
		delete oper;
		oper = nullptr;
	}
	system("pause");
	return 0;
}
           

簡單工廠模式的優缺點分析:

  • 優點: 工廠類是整個模式的關鍵所在。它包含必要的判斷邏輯,能夠根據外界給定的資訊,決定究竟應該建立哪個具體類的對象。 使用者在使用時可以直接根據工廠類去建立 所需的執行個體,而無需了解這些對象是如何建立以及如何組織的。有利于整個軟體體系結構的優化。
  • 缺點:由于工廠類集中了所有執行個體的建立邏輯,這就直接導緻一旦這個工廠出了問題,所有的用戶端都會受到牽連;而且由于簡單工廠模式的産品是基于一個共同的抽象類或者接口,這樣一來,一但産品的種類增加的時候,即有不同的産品接口或者抽象類的時候,工廠類就需要判斷何時建立何種種類的産品,這就和建立何種種類産品的産品互相混淆在了一起,違背了單一職責,導緻系統喪失靈活性和可維護性。
  • 而且更重要的是: 簡單工廠模式違背了“開放封閉原則”,就是違背了“系統對擴充開放,對修改關閉”的原則,因為當我們新增加一個産品的時候必須修改工廠類,相應的工廠類就需要重新編譯一遍。

總結一下:

  • 簡單工廠模式把産品的建立者和消費者分離,有利于軟體系統結構的優化;但是由于一切邏輯都集中在一個工廠類中,導緻了沒有很高的内聚性,同時也違背了“開放封閉原則”。
  • 另外,簡單工廠模式的方法一般都是靜态的,而靜态工廠方法是無法讓子類繼承的,是以,簡單工廠模式無法形成基于基類的繼承樹結構。

繼續閱讀