《4》工廠模式

概述:


工廠模式可分爲3小類:


簡單工廠、工廠方法、抽象工廠







  1. 簡單工廠


直接上例子:

public class Test {
	public static void main(String[] args) {
		int code;
		Duck duck;
		if(code == 1){
			duck = new DuckCall();
		}else if(code == 2){
			duck = new RubberDuck();
		}else if(code == 3){
			duck = new MallardDuck();			
		}else{
			duck = new RedHeadDuck();
		}
	}
}

以上ifelse 的部分,會隨着鴨子的種類變化面臨增刪

也會隨着客戶需求在不同的code下創建另一種Duck

根據封裝變化


得到簡單工廠

class SimpleDuckFactory{
	public Duck create(int code){
		Duck duck;
		if(code == 1){
			duck = new DuckCall();
		}else if(code == 2){
			duck = new RubberDuck();
		}else if(code == 3){
			duck = new MallardDuck();			
		}else{
			duck = new RedHeadDuck();
		}
		
		return duck;
	}
}


這種將創建對象的代碼移動到另一個類中,稱作簡單工廠


優勢:

1》一個工廠被提取出來後,就可以“擺脫”原來的單個客戶,面向多個客戶

2》而且修改的時候,也只要修改這個簡單工廠類即可










  1. 工廠方法

    上類圖(這次是Pizza店)

    父類Pizza是一個abstract類,其中createPizza()是一個虛擬方法,需要子類實現












上代碼:

父類:

public abstract class PizzaStore {
	Pizza order(){
		int type = 0;
		Pizza pizza = createPizza(type);
		pizza.prepare();
		return pizza;
	}
	abstract Pizza createPizza(int type);
}


子類:

public class NanjingPizzaStore extends PizzaStore{
	Pizza createPizza(){
		//這裏可以加入if else來進行擴展,如下第二個
		return new NanjingPizza();
	}
	
	Pizza createPizza(int type){
		Pizza pizza;
		switch(type){
		case 1:
			//仔雞味
			break;
		case 2:
			//咖喱味
			break;
		case 3:
			//番茄味
			break;
		default:
			//斷貨了
			break;
		}
		return pizza;
	}
}

給出定義:

定義了一個創建對象的接口,但是有子類決定具體實例化哪個類,工廠方法讓類把實例化操作推遲到子類



注意:

從上面的例子應該也可以看出,所謂的子類決定實例化哪一個Pizza,其實是通過父類的披薩店運行時選擇具體實現子類(例如:NanjingPizzaStore)來實現“動態”修改的效果。並不是子類在運行時決定,其實子類new哪個,是在代碼中寫死的(非動態)








  1. 抽象工廠

    設計原則5


依賴倒置原則 :儘量多依賴抽象,少依賴具體類


理解:爲啥叫依賴倒置,拿本文中的例子來解釋,你要創建一個Pizza店,首先是自上而下的思路來創建你的類框架,現在採取倒置思維,自下而上思考,總結下層依賴抽象成接口,這樣就是“儘量多依賴抽象,少依賴具體類”啦






抽象工廠理解:簡單工廠+工廠方法的組合


上類圖:


首先用簡單工廠,將new的代碼從上層類中摳出來,並對這個“變化”部分進行抽象,這時候在採用工廠方法來實現這個框架的剩餘部分




上代碼(這裏以Pizza店爲例):


抽象出一個Pizza的接口:

public abstract class Pizza {
	abstract String getDescription(); 
}


Pizza子類(雖然都是咖喱Pizza,但是上海的店和南京的店做出來的是口味不同的):

public class NanjingCurryPizza extends Pizza{

	@Override
	String getDescription() {
		return "南京咖喱味Pizza";
	}

}

public class ShanghaiCurryPizza extends Pizza{

	@Override
	String getDescription() {
		return "上海咖喱味Pizza";
	}

}


新建Pizza店:

public class PizzaStore {
	final int chicken = 0x1;
	final int curry = 0x2;
	
	PizzaFactory factory;
	//看到這裏依賴的並不是具體類,而是接口
	public PizzaStore(PizzaFactory factory){
		this.factory = factory;
	}
	
	Pizza order(int type){
		if(type == chicken){
			return factory.createChickenPizza();
		}else if(type == curry){
			return factory.createCurryPizza();
		}else{
			return null;
		}
	}
}



新建一個工廠抽象接口:

public interface PizzaFactory {
	Pizza createChickenPizza();
	Pizza createCurryPizza();
}


創建具體的南京&上海的Pizza工廠:

public class ShanghaiPizzaFactory implements PizzaFactory{

	@Override
	public Pizza createChickenPizza() {
		return new ShanghaiChickenPizza();
	}

	@Override
	public Pizza createCurryPizza() {
		return new ShanghaiCurryPizza();
	}

}

。。。南京就不列出了



理解:
Pizza店摳出創建Pizza的代碼,對這個代碼抽象成一個PizzaFactory接口,然後用到工廠方法寫出具體的實現子類,有南京的PizzaFactory和上海的PizzaFactory




抽象工廠定義:

提供一個接口,用於創建相關或者依賴的對象的家族,而不需要明確指定具體類



與工廠方法的區別:


1》工廠方法是通過繼承來實現,而抽象工廠是通過組合

2》工廠方法用來創建一個產品,而抽象工廠則是用來創建一個產品家族





抽象工廠缺點:

1》一旦產品家族裏新增成員,就必須修改抽象接口了



抽象工廠優點:

1》將客戶與具體產品解耦,封裝變化利於維護

2》因爲客戶使用的是一個接口,我們方便給客戶替換產品家族

3》而切抽象工廠接口可以面對多個客戶,代碼複用


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