設計模式之不簡單的工廠模式(二)

在這篇博客中,將講解工廠方法模式,需要再次強調一下凡是提到工廠模式都是用來產生對象用的,下面開始思考這麼一個場景:

小張喜歡吃烤魚,於是他走到他家附近的一家烤魚店,跟服務員說,我要烤鯉魚一份,然後找了個桌子,安心的坐下等待上菜,對於烤魚店來說,他們接收到小張下的烤鯉魚訂單,首先準備一條鯉魚,然後去清理,蒸熟,加上佐料烤,然後上桌,這麼個過程,首先先編寫一個魚類及其部分子類,如下:

public interface Fish {
	
	// 外觀展示
	public void display();
	
	// 是否是淡水魚
	public boolean isFWF();
	
}
/*
 * 鯉魚
 */
class Carp implements Fish{
	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println("我是一條鯉魚");
	}
	
	@Override
	public boolean isFWF() {
		// TODO Auto-generated method stub
		return true;
	}
}

/*
 * 鮎魚
 */
class CatFish implements Fish{
	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println("我是一條鮎魚");
	}
	
	@Override
	public boolean isFWF() {
		// TODO Auto-generated method stub
		return true;
	}
}

/*
 * 刀魚
 */
class KnifeFish implements Fish{
	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println("我是一條刀魚");
	}
	
	@Override
	public boolean isFWF() {
		// TODO Auto-generated method stub
		return false;
	}
}

下面在編寫烤魚店處理類,需要將該類聲明爲抽象類,並且在該類中提供一個抽象的工廠方法,代碼如下:

/*
 * 烤魚店
 */
public abstract class GrillFishStore {

	// 用戶下訂單的魚
	private Fish fish;

	// 訂單處理方法,其中過程包括準備一條鯉魚,然後清理,蒸熟,加上佐料烤,最後返回成品的烤魚
	public Fish orderFish(String fishType) {
		// 獲取用戶下訂單的魚
		fish = createFish(fishType);
		// 清理雜物
		cleanFish(fish);
		// 蒸熟
		steam(fish);
		// 加佐料烤
		roastWithSeasoning(fish);
		
		return fish;
	}
	
	// 清理
	public void cleanFish(Fish fish){
		
	}
	
	// 蒸熟
	public void steam(Fish fish){
		
	}
	
	// 佐料烤
	public void roastWithSeasoning(Fish fish){
		
	}
	
	// 獲取對應的魚類
	abstract Fish createFish(String fishType);
}

現在已經有了一個GrillFishStore作爲超類,在每個地區有若干個各種品牌的烤魚店,讓每個品牌的烤魚店都繼承這個GrillFishStore,每個子類各自決定如何製造魚類,子類如下:

/*
 * 諸葛烤魚,一個只對鯉魚和刀魚進行燒烤的烤魚店
 */
public class ZhugeGrillFishStore extends GrillFishStore {

	@Override
	public Fish createFish(String fishType) {

		if ("Carp".equals(fishType)) {
			return new Carp();
		} else if ("KnifeFish".equals(fishType)) {
			return new KnifeFish();
		} else
			return null;
	}

}
/*
 * 茅廬烤魚,一個只對鯉魚和鮎魚進行燒烤的烤魚店
 */
public class MaoluGrillFishStore extends GrillFishStore {

	@Override
	public Fish createFish(String fishType) {

		if ("Carp".equals(fishType)) {
			return new Carp();
		} else if ("CatFish".equals(fishType)) {
			return new CatFish();
		} else
			return null;
	}
}
這樣一來,將原本有一個簡單工廠類來負責實現所有具體類的實例化,現在通過對GrillFishStore做一些小轉變,編程由一羣子類來負責實例化;

工廠方法就是用來處理對象的創建,並將這樣的行爲封裝在子類中。這樣客戶程序關於超類的代碼就和子類對象創建代碼解耦:

	// abstract -> 工廠方法必須聲明爲抽象的,所以依賴子類來處理對象的創建
	// Product -> 工廠方法必須返回一個產品,通常使用工廠方法的返回值
	// factoryMethod -> 工廠方法將超類中的代碼(如orderFish方法)和實際創建具體產品的代碼分割開來
	// type -> 工廠方法可能需要參數(也可能不需要),來指定所要的產品
	abstract Product factoryMethod(String type);

工廠方法模式並不難理解,核心點在於超類用來聲明工廠方法,且限制流程,在子類中去實現具體對象的創建過程,如果對比簡單工廠的話,理解起來就會輕鬆很多!!當你沒事多讀讀源碼的話會發現有好多的源碼都採用的是工廠方法模式!

所有工廠模式都用來封裝對象的創建。工廠方法模式通過讓子類決定該創建的對象是什麼,來達到將對象創建的過程封裝的目的,下面讓我們來看看類圖:


GrillFishStore類就是創建者類,它定義了一個抽象的工廠方法,讓子類實現此方法制造產品,創建者通常會包含依賴於抽象產品的代碼,而這些抽象產品由子類創造,創建者不需要指的知道在製造哪種具體產品,MaoluGrillFishStore和ZhugeGrillFishStore類是GrillFishStore類的子類,所以可以實現createFish方法創建自己的對象;

工廠方法模式定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。工廠方法讓類把實例化推遲到了子類;工廠方法模式能夠封裝具體類型的實例化。在抽象的創建者類中,任何其它實現的方法,都可能使用到這個工廠方法所製造出來的產品,但只有子類真正實現這個工廠方法並創建產品。

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