設計模式學習(1) --- 3類工廠模式

YunShell發表於2014-10-22

   講個故事吧。從前一個老闆非常有錢,非常喜歡數碼產品手機,經常喜歡買智慧手機,那麼怎麼買?當然,可以自己去各個手機店買,比如去蘋果店,三星店買。但是老闆是非常忙的,怎麼辦?老闆是程式設計師出生。物件導向嘛。加個層次,叫祕書去買,把要買的型號,寫張紙條給祕書即可。為什麼這樣做,對老闆來說當然省事了,直接竊取祕書的勞動成果即可(因為付薪水了嘛)。祕書根據老闆的指示去做,要買什麼牌子手機就去相應的專賣店買即可。OK,這樣應付了一段時間,因為這個時期智慧手機剛剛興起,也就幾家可以做。

       時光飛逝,歲月如梭。隨著科技的進步,智慧手機市場太大,至於處於一個智慧手機的元年,用某人的話說“風口上,豬都能飛起來”。所以,一大批智慧手機廠商出現,一大批智慧手機品牌出現,但是這個老闆從喜歡買智慧手機到喜歡收集研究智慧手機了,因為土豪嘛,不差錢。所以知道哪裡又出款手機了,就叫祕書去買,天啊。這下可忙壞了祕書,要知道,世上的智慧手機品牌這麼多,祕書的工作現在負擔變得更重了,不光要負責公司各種會議,還要天天出去買手機,心裡甚是不爽。當然,老闆看在眼裡,就加了祕書的工資,並且給祕書配了幾個同事協助祕書買智慧手機這件事。祕書加薪了又有同事一起來分擔,祕書這下爽了,這是要升職加薪充當CEO迎娶高富帥的節奏啊,頓時高興起來了。而且祕書又是總管。老闆要買什麼新品牌手機,都是跟祕書先說,然後祕書在去分配其他同事分頭去買。當然為此老闆需要多些人工費,土豪嘛,這能有幾個錢。ok這樣又過了一段時間。

       時間飛逝,歲月如梭。隨著各大手機廠商的產品迭代,尼瑪iphone都出到了6了。老闆收集起來更加瘋狂了,要把所有品牌的所有型號都買回來研究。這下又忙壞了祕書,因為祕書要搞清楚哪些個品牌都產到幾代了,這當然也不是什麼太大的難事,百度一下嘛,ok,在瞭解了各個品牌的系類產品後,再吩咐其他同事分別去買各個系列產品。當然如果產品品類太多,再增加個同事嘛。多付幾個人力費而已。

      最後土豪老闆就這樣將所有智慧手機體驗了個遍,都覺得不行,沒有抓住消費者發燒心裡,於是打算自己幹一款產品,於是安靜的建立了一家公司,勢必要打造一款全球級別的重量級智慧手機...美好的事情即將發生....那麼問題來了,使用設計模式哪家強?

1.簡單工廠模式(simple factory)

     OK,小學語文老師教會了我們在分析語文課文時,按照自然段來劃分中心思想。在第一段自然中程式設計師老闆成分利用了自己所學的專長,將實際買手機問題,變成了物件導向問題(面向祕書哇!好幸福)。祕書具有按照老闆要求買手機的功能。這個祕書就是工廠了(神馬祕書是工廠?)抽象為工廠啦!專門做一間買各種品牌手機的事。而對於手機而言,需不需要抽象?各大手機廠商,也不太可能造晶片,螢幕等配件,所以也是個具有技術含量的零配件組裝廠,所以可以具體抽象出行為(具有發簡訊,打電話,上網等功能的裝置),各個實際手機廠商按照各自設計來設計。於是java程式碼如下:

//抽象類實現
abstract class phone
{ //抽象類至少一個抽象方法 這樣才是抽象類
	abstract void phoneInf(); 
}
//具體產品
class iphone extends phone
{
	public void phoneInf()
	{
		System.out.println("Buy iphone");
	}
}
class XiaoMi extends phone
{
	public void phoneInf()
	{
		System.out.println("Buy XiaoMi");
	}
}
//工廠
class Secretary
{
	public static phone BuyPhone(String brand)
	{
		if(brand.equals("iphone") )
			return new iphone();
		else 
		{
			if( brand.equals("XiaoMi") )
				return new XiaoMi();
			else 
				return null;
		}
	}
}

class Main
{
	public static void main(String[] args)
	{ //老闆只需要告訴祕書買什麼牌子的手機即可
		phone p1 = Secretary.BuyPhone("XiaoMi");
		p1.phoneInf();
		
		phone p2 = Secretary.BuyPhone("iphone");
		p2.phoneInf();
	}
}

/************************************************************************/
/* C++實現 簡單工廠模式 
 */
/************************************************************************/
#include <iostream>
#include <string>
using namespace std;

class Phone
{
public :
	virtual void phoneInf() =0; //純虛擬函式 
};

class iPhone : public Phone
{
public:
	void phoneInf()
	{
		cout<<"Buy iPhone"<<endl;
	}
};
class XiaoMi : public Phone
{
public :
	void phoneInf()
	{
		cout<<"Buy XiaoMi"<<endl;
	}
};

class Secretary
{
public:
	static Phone* BuyPhone(string brand)
	{
		if(brand == "iPhone")
			return new iPhone();
		else 
		{
			if(brand == "XiaoMi")
				return new XiaoMi();
			else 
				return NULL;
		}
	}
};

int main()
{
	Phone* p1 = Secretary::BuyPhone("iPhone");
	p1->phoneInf();

	Phone* p2 = Secretary::BuyPhone("XiaoMi");
	p2->phoneInf();
	return 0;
}

從上可見簡單工廠模式組成:

         a.工廠類(這裡是祕書),核心部分。由一個具體的類實現。

         b.抽象產品。 (這裡是phone),java中由一個介面或者抽象類實現。C++中可以由抽象類(含有純虛擬函式的類)實現。

         C.具體產品。這裡指的是各個手機廠商產生的產品,比如iphone,xiaomi等。java中繼承或者實現 抽象類和介面,完成實際產品例項的建立。C++中子類例項化物件。

      這樣做,老闆(實際客戶)只提出請求,執行全部將由祕書(工廠類)來做。其中工廠類必須具有邏輯判斷等一些功能,比如祕書要能分辨各種手機品牌的功能。這樣子,資料量小時候,完全可以這麼做。一旦老闆需要有些新手機,但是資料量較小時候,祕書就需要在買一些品牌了(對於工廠類而言,就是需要在修改類了)。

2.工廠方法模式(factory method)

  第二自然段告訴我們,當祕書實在忙不過來了,頻繁的修改工廠類,相當於導致祕書工作量巨大,必須有人來幫忙才行。這下祕書只管負責安排任務,具體的手機叫手下買了,再給祕書即可。這時候,需要增加一個抽象工廠類,用於只分發任務功能,具體的工作由實際工廠來做。程式碼如下:

//java 工廠方法模式 
//抽象產品
abstract class phone
{ 
	public abstract void phoneInf(); 
}
//具體產品
class iphone extends phone
{
	public void phoneInf()
	{
		System.out.println("Buy iphone");
	}
}
class XiaoMi extends phone
{
	public void phoneInf()
	{
		System.out.println("Buy XiaoMi");
	}
}
//抽象工廠類
abstract class Secretary
{
	public abstract phone BuyPhone();
}

//實際工廠類
class PersonA_iphone extends Secretary
{
	public phone BuyPhone()
	{
		return new iphone();
	}
}
class PersonB_XiaoMi extends Secretary
{
	public phone BuyPhone()
	{
		return new XiaoMi();
	}
}

class Main
{
	public static void main(String[] args)
	{ 
		//祕書分配person1去買iphone
		PersonA_iphone person1 = new PersonA_iphone() ;
		phone p1 = person1.BuyPhone();
		p1.phoneInf(); 
		//祕書分配person2去買XiaoMi
		PersonB_XiaoMi person2 = new PersonB_XiaoMi();
		phone p2 = person2.BuyPhone();
		p2.phoneInf();
	}
}
/************************************************************************
 C++實現 工廠方法模式 
************************************************************************/
#include <iostream>
#include <string>
using namespace std;

class Phone
{
public :
	virtual void phoneInf() =0; //純虛擬函式 
};

class iPhone : public Phone
{
public:
	void phoneInf()
	{
		cout<<"Buy iPhone"<<endl;
	}
};
class XiaoMi : public Phone
{
public :
	void phoneInf()
	{
		cout<<"Buy XiaoMi"<<endl;
	}
};

//抽象工廠
class Secretary
{
public:
	virtual Phone* BuyPhone()= 0 ;
};
//實際工廠 
class PersonA_iphone : public Secretary
{
public:
	Phone* BuyPhone()
	{
		return new iPhone();
	}
};
class PersonB_XiaoMi : public Secretary
{
public:
	Phone* BuyPhone()
	{
		return new XiaoMi();
	}
};
int main()
{
	//祕書叫person1 去買iphone
	PersonA_iphone person1 ;
	Phone*  phone1 = person1.BuyPhone();
	phone1->phoneInf();
	
	//祕書叫person2 去買xiaomi
	PersonB_XiaoMi person2 ;
	Phone* phone2 = person2.BuyPhone();
	phone2->phoneInf();

	return 0;
}

從上可見工廠方法模式組成:

         a. 抽象產品。 (這裡是phone),java中由一個介面或者抽象類實現。C++中可以由抽象類(含有純虛擬函式的類)實現。

         b.具體產品。這裡指的是各個手機廠商產生的產品,比如iphone,xiaomi等。java中繼承或者實現 抽象類和介面,完成實際產品例項的建立。C++中子類例項化物件。

       c. 抽象工廠類(這裡是祕書),相比於簡單工廠模式,增加的,將祕書從實際勞力中解放出來,只負責安排任務,由一個抽象類實現。

      d.實際工廠。指的是 實際買手機的人。實際類例項化。

      這樣將導致,祕書輕鬆了許多,具體買手機這件事,也比較好做,只要人手夠多,一旦要新買個手機,只需要祕書在派個人即可,這樣對於祕書而言,依然輕鬆,可擴充套件。但是唯一的壞處就是需要花錢僱傭人手,多應於實際程式碼張就是要多很多實際的類。whatever,事情可以達到要求嘛。

3.抽象工廠模式

  第三自然段告訴我們,手機廠商都出系列手機了,前兩模式都不適用了,總不可能祕書吩咐A去買iphone1,又叫B去買iphone2吧..當然也可以,但是沒必要啊。買iPhone1的肯定可以去買iphone2嘛。所以祕書需要從新規劃下任務清單,好重新安排任務了。

//java 抽象工廠模式
//抽象產品類
abstract class phone
{ 
	public abstract void phoneInf(); 
}
//具體產品
class iphone1 extends phone
{
	public void phoneInf()
	{
		System.out.println("Buy iphone1");
	}
}
class iphone1s extends phone
{
	public void phoneInf()
	{
		System.out.println("Buy iphone1s");
	}
}
class XiaoMi1 extends phone
{
	public void phoneInf()
	{
		System.out.println("Buy XiaoMi1");
	}
}
class XiaoMi1s extends phone
{
	public void phoneInf()
	{
		System.out.println("Buy XiaoMi1s");
	}
}
//抽象工廠類
abstract class Secretary
{
	public abstract phone BuyPhone_1();//買一代手機
	public abstract phone BuyPhone_1s(); //買一代升級版
	//public abstract phone BuyPhone_2(); //買二代手機
	//繼續擴充套件...
}

//實際工廠類
class PersonA_iphone extends Secretary
{
	public phone BuyPhone_1()//買iphone一代手機
	{
		return new iphone1();
	}
	public phone BuyPhone_1s()//買iphone1s版
	{
		return new iphone1s();
	}
}
class PersonB_XiaoMi extends Secretary
{
	public phone BuyPhone_1()
	{
		return new XiaoMi1();
	}
	public phone BuyPhone_1s()
	{
		return new XiaoMi1s();
	}
}

class Main
{
	public static void main(String[] args)
	{ 
		//祕書分配person1去買iphone1,1s產品
		PersonA_iphone person1 = new PersonA_iphone() ;
		phone p1 = person1.BuyPhone_1();//personA 買的iphone1
		phone p2 = person1.BuyPhone_1s();//personA 買的iphone1s
		p1.phoneInf(); 
		p2.phoneInf();
		
		//祕書分配person2去買XiaoMi1,1s產品
		PersonB_XiaoMi person2 = new PersonB_XiaoMi();
		phone p3 = person2.BuyPhone_1();
		p3.phoneInf();
		phone p4 = person2.BuyPhone_1s();
		p4.phoneInf();
	}
}

/***********************************************************************
C++實現 抽象工廠模式
*********************************************************************/
#include <iostream>
#include <string>
using namespace std;
//抽象產品類
class Phone
{
public :
	virtual void phoneInf() =0; //純虛擬函式 
};
//實際產品
class iPhone1 : public Phone
{
public:
	void phoneInf()
	{
		cout<<"Buy iPhone1"<<endl;
	}
};
class iPhone1s : public Phone
{
public:
	void phoneInf()
	{
		cout<<"Buy iPhone1s"<<endl;
	}
};
class XiaoMi1 : public Phone
{
public :
	void phoneInf()
	{
		cout<<"Buy XiaoMi1"<<endl;
	}
};
class XiaoMi1s : public Phone
{
public :
	void phoneInf()
	{
		cout<<"Buy XiaoMi1s"<<endl;
	}
};
//抽象工廠
class Secretary
{
public:
	virtual Phone* BuyPhone1()= 0 ; //買一代手機
	virtual Phone* BuyPhone1s()=0;  //買1s手機
	//...繼續擴充套件
};
//實際工廠 
class PersonA_iphone : public Secretary
{
public:
	Phone* BuyPhone1()
	{
		return new iPhone1();
	}
	Phone* BuyPhone1s()
	{
		return new iPhone1s();
	}

};
class PersonB_XiaoMi : public Secretary
{
public:
	Phone* BuyPhone1()
	{
		return new XiaoMi1();
	}
	Phone* BuyPhone1s()
	{
		return new XiaoMi1s();
	}
};
int main()
{
	//祕書叫person1 去買iphone1,1s
	PersonA_iphone person1 ;
	Phone*  phone1 = person1.BuyPhone1();
	Phone*  phone2 = person1.BuyPhone1s();
	phone1->phoneInf();
	phone2->phoneInf();

	//祕書叫person2 去買xiaomi1,1s
	PersonB_XiaoMi person2 ;
	Phone* phone3 = person2.BuyPhone1();
	Phone* phone4 = person2.BuyPhone1s();
	phone3->phoneInf();
	phone4->phoneInf();

	return 0;
}
分析組成:和工廠方法模式一樣:

         a. 抽象產品。 (這裡是phone),java中由一個介面或者抽象類實現。C++中可以由抽象類(含有純虛擬函式的類)實現。

         b.具體產品。這裡指的是各個手機廠商產生的產品,比如iphone1,1s,xiaomi1等。java中繼承或者實現 抽象類和介面,完成實際產品例項的建立。C++中子類例項化物件。

        c. 抽象工廠類(這裡是祕書),相比於簡單工廠模式,增加的,將祕書從實際勞力中解放出來,只負責安排任務,由一個抽象類實現。但是對於這樣的產品族而言,需要重新設計祕書類了。如本例中。

       d.實際工廠。指的是 實際買手機的人。實際類例項化。


相關文章