設計模式學習(二) 簡單工廠模式

今天我學習了一下簡單工廠模式,其實簡單工廠模式並不被包含於GoF 23種設計模式中,但也是會被頻繁的使用在開發中,而且也算是其它工廠模式學習的入門吧。

首先,我想通過一個例子,引入今天的主題。如果我要設計一個學校職工信息管理系統,我要向服務器請求老師、學生、和其他工作人員的基本信息,那我們應該會如何進行設計呢?在不瞭解各種面向對象設計模式的時候,我們很容易想到的一種方法就是,先定義三個類分別是Student類、Teacher類、Other類,這三個類中分別存放了不同的對應相應類的屬性。然後定義一個People類用來繼承前面定義的三個類,並在其中加入一個classType來幫助返回我要請求的類中的數據。於是我們很容易寫出瞭如下代碼:

class People: public Student,public Teacher,public Other
{
private:
	string type;
public:
	People(string myType)
	{
		this->type = myType;
		switch(this->type)
		{
		case "Student":{
		//初始化學生信息
		}break;
		case "Teacher":{
		//初始化教師信息
		}break;
		case "Other":{
		//初始化其他員工信息
		}break;
		default:break;
		}
	}
	
	void display()
	{
		if(this->type == "Student")
		{
			//輸出學生信息
		}
		else if(this->type == "Teacher")
		{
			//輸出教師信息
		}
		else if(this->type == "Other")
		{
			//輸出其他員工信息
		}
	}
}

毫無疑問,這個類是可以達到我們所需要達到的目的的,但是我們對照面向對象的設計原則,我們還是發現了許多問題:

1、People類的職責太重了,同時要完成所有的初始化和打印兩方面功能,違反了單一職責原則。

2、如果我今後要擴充功能,加入行政人員的資料查詢,那麼我還將要重新修改代碼,將類中的if/else判斷再加上一句,增加了添加模塊的難度,違反了開閉原則。

3、客戶只能用new關鍵字來創建對象,類和客戶端的耦合程度太高。


OK!那就上面三點,我們可以使用簡單工廠模式進行怎樣的改進呢?

首先,我們要了解,簡單工廠模式中的三個角色:

(1)工廠角色:這是該模式的核心部分,負責創建所有產品(對象),同時工廠可以被外界直接調用,創建所需產品的對象。

(2)抽象產品角色:工廠類所創建所有產品(對象)的父類,封裝了所有產品的公有方法,用於提高系統的靈活性。

(3)具體產品角色:該模式的創建目標,由他創建對象都是某個具體類的實例(ps:結合上面的例子,就可以理解爲Student類、Teacher類、Other類,他們都包含自己特有的屬性)


那麼,接下來我們就要開始實現了!!

第一步是抽象產品角色,我們要實現的功能是打印功能,因此,我們就需要一個只有display()功能的類,記住要是一個虛基類,因爲作爲一個接口類,我不需要在類中實現功能。

第二步要開始寫我們的具體產品角色了,每個類中的屬性有所不同,但是要記住的是:一定要公有繼承,抽象產品類,並在自己類中寫display()函數。

第三步,也是最重要的一步,我們要在工廠類中,做出邏輯判斷,寫一個靜態函數,通過傳進的參數來判斷是要請求哪種產品(即Student\Teacher\Other)的參數。


下面給出我寫的一個模板的代碼(我並沒有實現我之前舉得例子,因爲我學的時候,並沒有用這個例子寫代碼)


/*
 * class.h
 *
 *  Created on: 2014-3-20
 *      Author: linux
 */

#ifndef CLASS_H_
#define CLASS_H_

#include <iostream>

class DisplayInterface
{
public:
	virtual void Display(){

	};
};

class ClassA :public DisplayInterface
{
public:
	ClassA(){
		std::cout<<"create class A"<<std::endl;
	}
	~ClassA(){

	}
	virtual void Display();
};

class ClassB :public DisplayInterface
{
public:
	ClassB(){
		std::cout<<"create class B"<<std::endl;
	}
	~ClassB(){

	}
	virtual void Display();
};

class ClassC :public DisplayInterface
{
public:
	ClassC(){
		std::cout<<"create class C"<<std::endl;
	}
	~ClassC(){

	}
	virtual void Display();
};

void ClassA::Display(){
	std::cout<<"display class A"<<std::endl;
}

void ClassB::Display(){
	std::cout<<"display class B"<<std::endl;
}

void ClassC::Display(){
	std::cout<<"display class C"<<std::endl;
}


class SimpleFactory
{
public:
	static DisplayInterface* getClass(int type) {
		DisplayInterface* classPtr = nullptr;
		switch(type)
		{
		case 1:classPtr = new ClassA;break;
		case 2:classPtr = new ClassB;break;
		case 3:classPtr = new ClassC;break;
		}
		return classPtr;
	}
};
#endif /* CLASS_H_ */

主函數的代碼如下


#include <iostream>
#include "class.h"
using namespace std;

int main()
{
	DisplayInterface* ptr = SimpleFactory::getClass(1);
	ptr->Display();
	ptr = SimpleFactory::getClass(2);
	ptr->Display();
	ptr = SimpleFactory::getClass(3);
	ptr->Display();
}


當然簡單工廠模式還是可以簡化的,就是將抽象產品角色和工廠合併帶一個類中。這個讀者自己可以嘗試一下。


最後介紹的是適用場景:

1、工廠類創建的對象比較少,以免工廠類太過於繁瑣

2、客戶端只需要知道往工廠傳入參數,而並不需要關心對象時如何創建的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章