工廠模式的形態

工廠模式的形態
工廠模式主要用一下幾種形態:
1:簡單工廠(Simple Factory)。
2:工廠方法(Factory Method)。
3:抽象工廠(Abstract Factory)。



簡單工廠(Simple Factory)
又叫靜態工廠,是工廠模式三中狀態中結構最爲簡單的。有一個靜態方法,用來接受參數,根據參數決定返回實現同一接口的不同類的實例。我們來看一個演唱會工廠具體的例子:
假設一場演唱會,根據觀衆要求,會請來明星:劉德華,張學友,陳奕迅. . . . . .(爲什麼沒有女的?)
我們先爲所有明星們定義一個接口
package 簡單工廠;


public interface Star {
}

接着我們讓這個演唱會的所有明星都實現此接口
package 簡單工廠;


public class 劉德華 implements Star {
	public 劉德華() {
		System.out.println("劉德華在唱歌");
	}
}


class 陳奕迅 implements Star {
	public 陳奕迅() {
		System.out.println("陳奕迅在唱歌");
	}
}


class 張學友 implements Star {
	public 張學友() {
		System.out.println("張學友在唱歌");
	}
}

接下來我們來寫一個演唱會的類,(方法名不是factory了,感覺怪怪的)由它來負責邀請明星
package 簡單工廠;


public class Concert {
	
	public static Star 個人專場(String starName) throws Exception {
		if (starName.equals("劉德華")) {
			return new 劉德華();
		}
		else if (starName.equals("張學友")) {
			return new 張學友();
		}
		else if (starName.equals("陳奕迅")) {
			return new 陳奕迅();
		}
		else {
			throw new Exception("沒有該明星");
		}
	}
}


好了,有了這個演唱會類,我們就可以喊話了,Concert將根據不同的名字來決定哪個明星(順帶複習finally)。
好了,演唱會上半場:
package 簡單工廠;


public class Test {
	public static void main(String[] args) {
		System.out.println("是誰在唱歌?");
		try {
			Concert.個人專場("劉德華");
			Concert.個人專場("張學友");
			Concert.個人專場("陳奕迅");
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			System.out.println("溫暖了寂寞");
		}
	}
}



可以看出,簡單工廠的核心就是一個Concert類,他擁有判斷能力和創建對象的控制權,我們只需要向他喊話,就能得到我們想要的明星,是不是很爽?實際上,這個Concert有很多的侷限。
1、我們每次想要增加一個新明星的時候,都必須修改Concert的原代碼,例如叫上楊千嬅。
if (starName.equals("楊千嬅")) {
			return new 楊千嬅();
		}
2、當我們擁有很多很多明星的時候,而且明星之間又有複雜的附屬關係的時候(例如團隊:鳳凰傳奇),這個類必須擁有複雜的邏輯判斷能力,其代碼量也將不斷地增加,邀請就麻煩了,那演出就開不成了?
3、整個系統都嚴重依賴Concert類,只要Concert類一出問題,
德華和學友就唱不成了啊!
德華和學友就唱不成了啊!
德華和學友就唱不成了啊!
這也是最爲致命的一點....


那怎麼可以?於是,工廠模式帶你嗨翻天. . . . . . . 




工廠方法(Factory Method)
工廠方法爲演唱會類定義了接口,用多態來削弱了演唱會類的職能,以下是工廠接口的定義:
package 工廠方法;


public interface Concert {
	public Star 個人專場();
}

我們再來定義一個明星接口
package 工廠方法;


public interface Star {
	
}

下面是實現了明星接口的明星類
package 工廠方法;


public class 劉德華 implements Star {
	public 劉德華() {
		System.out.println("劉德華在唱歌");
	}
}


class 陳奕迅 implements Star {
	public 陳奕迅() {
		System.out.println("陳奕迅在唱歌");
	}
}


class 張學友 implements Star {
	public 張學友() {
		System.out.println("張學友在唱歌");
	}
}

接下來,就是工廠方法的核心部分,也就是具體創建明星對象的具體演唱會類
<pre name="code" class="html">package 工廠方法;


public class Concert劉德華 implements Concert {
	public Star 個人專場() {
		return new 劉德華();
	}
}


//創建張學友演唱會的工廠 
class Concert張學友 implements Concert {
	public Star 個人專場() {
		return new 張學友();
	}
}



//創建陳奕迅演唱會的工廠 
class Concert陳奕迅 implements Concert {
	public Star 個人專場() {
		return new 陳奕迅();
	}
}





演唱會下半場
package 工廠方法;


public class Test {
	public static void main(String[] args) {
		System.out.println("是誰在唱歌?");
		try {
			Concert 劉德華 = new Concert劉德華();
			劉德華.個人專場();
			
			Concert 張學友 = new Concert張學友();
			張學友.個人專場();
			
			Concert 陳奕迅 = new Concert陳奕迅();
			陳奕迅.個人專場();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}







從上面創建明星對象的代碼可以看出,工廠方法和簡單工廠的主要區別是:
簡單工廠把創建明星的職能都放在一個演唱會類,工廠方法把不同的明星放在實現了工廠接口的不同演唱會類,這樣就算其中一個演唱會類出了問題,其他演唱會類也能正常工作,互相不受影響,以後增加新明星,也只需要新增一個新的明星演唱會的工廠類,就可以了,不用修改已有的代碼。
工廠方法也有他侷限的地方,那就是當面對的全能或半能的明星時,就像舞王、歌王、歌舞王,你總不能叫劉歡去跳舞吧,所以,你的演唱會就要分門別類了,簡單點~~~,唱歌中間,跳舞右邊,歌舞中間(阿三,你走哪裏,中間別動!)當這些情況交織時,就形成了一個複雜的明星樹了。
如果用工廠方法來設計這個明星家族系統,就必須爲每種明星創建一個對應的演唱會類,當有數百種甚至上千種明星的時候,也必須要有對應的上百成千個演唱會類,這就出現了傳說的類爆炸,簡直就是一場災難,那還開不開?開!!!!!


抽象工廠(Factory Method)
抽象工廠:意的意圖在於創建一系列互相關聯或互相依賴的對象。<<Java設計模式>>
抽象工廠是在工廠方法的基礎上引進了分類管理的概念(這個很重要). . . . . 
工廠方法用來創建一個明星,它沒有分類的概念,而抽象工廠則用於創建一系列明星,所以明星分類成了抽象工廠的重點。


剛纔你們聽的嗨不嗨,那就來個不散場吧!!!!


明星嘛,歌王(張學友),舞王(郭富城),歌舞王(王邁克傑克遜),這就是對應明星的種類,所有明星都會加入不同的club,就形成了明星樹


首先,進行分類:


劉德華:
唱歌的劉德華
跳舞的劉德華
張學友:
唱歌的張學友
跳舞的張學友
陳奕迅:
唱歌的陳奕迅
跳舞的陳奕迅


我們可以爲明星們分別定義兩個明星接口,以對他們進行分類
package 抽象工廠;


public interface 劉德華 {
}


interface 陳奕迅 {
}


interface 張學友 {
}





接着,我們來實現接口
package 抽象工廠;


public class 唱歌的劉德華 implements 劉德華 {
	public 唱歌的劉德華() {
		System.out.println("唱歌的劉德華");
	}
}


class 跳舞的劉德華 implements 劉德華 {
	public 跳舞的劉德華() {
		System.out.println("跳舞的劉德華");
	}
}


class 唱歌的陳奕迅 implements 陳奕迅 {
	public 唱歌的陳奕迅() {
		System.out.println("唱歌的陳奕迅");
	}
}


//陳奕迅跳舞不行啊,不管了
class 跳舞的陳奕迅 implements 陳奕迅 {
	public 跳舞的陳奕迅() {
		System.out.println("跳舞的陳奕迅");
	}
}


class 唱歌的張學友 implements 張學友 {
	public 唱歌的張學友() {
		System.out.println("唱歌的張學友");
	}
}


class 跳舞的張學友 implements 張學友 {
	public 跳舞的張學友() {
		System.out.println("跳舞的張學友");
	}
}






到此,明星部分我們準備好了,接下來我們來處理演唱會部分,我們先來定義接口
package 抽象工廠;


public interface Concert {
	
	public 劉德華 create劉德華();
	
	public 張學友 create張學友();
	
	public 陳奕迅 create陳奕迅();
}

接下來我創造具體的演唱會類,我們根據上面明星的接口,把唱歌的明星分爲一類,由一個演唱會來管理,把跳舞的明星有另一個演唱會管理,根據這個分類,我們可以實現如下的兩個具體演唱會類
package 抽象工廠;


//創建唱歌的演唱會
public class 演唱會 implements Concert {
	
	public 劉德華 create劉德華() {
		return new 唱歌的劉德華();
	}
	
	public 張學友 create張學友() {
		return new 唱歌的張學友();
	}
	
	public 陳奕迅 create陳奕迅() {
		return new 唱歌的陳奕迅();
	}
	
}


//創建跳舞的演唱會(演跳會)
class 演跳會 implements Concert {
	
	public 劉德華 create劉德華() {
		return new 跳舞的劉德華();
	}
	
	public 張學友 create張學友() {
		return new 跳舞的張學友();
	}
	
	public 陳奕迅 create陳奕迅() {
		return new 跳舞的陳奕迅();
	}
}






這樣,我們的抽象工廠就完成了。Music!
package 抽象工廠;


public class Test {
	public static void main(String[] args) {
		Concert 唱歌 = new 演唱會();
		
		劉德華 劉德華唱歌 = 唱歌.create劉德華();
		張學友 張學友唱歌 = 唱歌.create張學友();
		陳奕迅 陳奕迅唱歌 = 唱歌.create陳奕迅();
		
		Concert 跳舞 = new 演跳會();
		
		劉德華 劉德華跳舞 = 跳舞.create劉德華();
		張學友 張學友跳舞 = 跳舞.create張學友();
		陳奕迅 陳奕迅跳舞 = 跳舞.create陳奕迅();
		
	}
}

散場別忘了點個贊o!

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