簡單工廠和工廠方法模式

一.前言

 1.準備好開始烘烤某些鬆耦合OO設計

 2.製造對象的方法除了new,還有很多其他的方法;

 3.初始化使用new經常會帶來一些耦合的問題,工廠模式可以解決這個問題;

   那麼“new”有什麼不對勁呢?

  其實,new沒有問題,有問題的是“改變”。則可以用設計原則“找出會變化的部分,把他們從不變的部分分離出來”

 (即:將實例化具體類的方法抽離,或者封裝起來,使他們不會干擾其他部分。)

 4.重要原則--“針對接口編程”。

 5.所有工廠模式都是用來封裝對象的創建。

二.披薩店實例--簡單工廠

 1.pizza店有許多pizza類型,每種pizza從order開始的流程都要經過準備prepare、烘烤bake、切片cut和裝箱box,所以通常對於OO設計者們,初步可以考慮到這樣的設計:

wKioL1cPBd3TvXEFAABS7rX5jZ4174.png

public class MainTest {
	public static void main(String[] args) {
		IPizza pizza = orderPizza(null);
		if(pizza != null){
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
		}
	}
	
	private static IPizza orderPizza(String type){
		if(type == null){
			System.out.println("What kind of pizza do you want?");
			return null;
		}
		IPizza pizza = null;
		if(type.equals("cheese")){
			pizza = new PizzaCheese();
		}else if(type.equals("fruit")){
			pizza = new PizzaFruit();
		}else if(type.equals("banana")){
			pizza = new PizzaBanana();
		}
		return pizza;
	}
}
public interface IPizza {

	/**準備*/
	public void prepare();
	/**烘烤*/
	public void bake();
	/**切片*/
	public void cut();
	/**裝盒*/
	public void box();
}
public class PizzaCheese implements IPizza{

	public void prepare() {
		System.out.println("PizzaCheese prepare");
	}

	public void bake() {
		System.out.println("PizzaCheese bake");
	}

	public void cut() {
		System.out.println("PizzaCheese cut");
	}

	public void box() {
		System.out.println("PizzaCheese box");
	}

}

 2.上述中存在一個問題:增加新類型pizza或去除一種賣的不好的pizza,上述創建pizza對象的部分就要一改再改,這裏就是變化的部分,我們要做的,就是分離變化的部分----該使用封裝了。

   封裝創建對象的代碼

  (1)將創建對象的代碼移到另一個對象中,這個對象的專職就是創建pizza對象;

  (2)稱這個專職對象爲“工廠”SimplePizzaFactory;

  (3)此時,orderPizza()就不再需要知道什麼類型的pizza,只管得到一個pizza。

wKiom1cPD2OiD3e0AABaICBLPbA835.png

    

//測試類
public class MainTest {
	public static void main(String[] args) {

		//利用工廠創建pizza
		IPizza pizza = new PizzaShop().orderPizza("banana");

		if(pizza != null){
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
		}
	}
}
//客戶預訂披薩
class PizzaShop{
	public IPizza orderPizza(String type){
		//利用工廠創建pizza
		IPizza pizza = SimplePizzaFactory.createPizza(type);
		return pizza;
	}

}
public class SimplePizzaFactory {
	/**
	 * 把原來的創建代碼直接移動過來
	 * @param type
	 * @return
	 */
	public static IPizza createPizza(String type){
		if(type == null){
			System.out.println("What kind of pizza do you want?");
			return null;
		}
		IPizza pizza = null;
		if(type.equals("cheese")){
			pizza = new PizzaCheese();
		}else if(type.equals("fruit")){
			pizza = new PizzaFruit();
		}else if(type.equals("banana")){
			pizza = new PizzaBanana();
		}
		return pizza;
	}
}

 其他部分不變,此後:

  當有很多很多“客戶”時,他們都利用該“工廠”創建指定類型的pizza,如果pizza本身種類等發生任何改變,每個“客戶”都不用修改代碼,只需“工   廠”修改即可


 3.以上就是“簡單工廠”:

   簡單工廠其實並不是一個設計模式,而是一種編程習慣;

   簡單工廠常用爲static,但有時也有缺點,不能利用繼承待改變創建方法的行爲。


三.披薩店實例--工廠方法

 1.現有不同區域的披薩店想要做不同口味的披薩。就不能用簡單工廠了。可以考慮將創建對象的功能移到pizzashop的一個抽象方法中,由pizzashop的子類做決定創建具體的對象

wKiom1cPJTKyh4eTAABNiaBEQAY422.png

public abstract class PizzaShop {
	// final的修飾不是必要的,不過這樣可以防止子類覆蓋
	public final IPizza orderPizza(String type){
		
		// createPizza()移回PizzaShop中
		IPizza pizza = createPizza(type);
		
		if(pizza != null){
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
		}
		return pizza;
	}
	// 抽象的“工廠方法”
	protected abstract IPizza createPizza(String type);
}
// 每個子類都要繼承PizzaShop
public class BeijingPizzaShop extends PizzaShop{
	// 實現抽象的“工廠方法”
	protected IPizza createPizza(String type) {
		if(type == null){
			System.out.println("BeijingPizzaShop:What kind of pizza do you want?");
			return null;
		}
		IPizza pizza = null;
		if(type.equals("cheese")){
			pizza = new BeijingPizzaCheese();
		}else if(type.equals("fruit")){
			pizza = new BeijingPizzaFruit();
		}else if(type.equals("banana")){
			pizza = new BeijingPizzaBanana();
		}
		return pizza;
	}

}
public class ShenZhenPizzaShop extends PizzaShop{

	protected IPizza createPizza(String type) {
		if(type == null){
			System.out.println("ShenZhenPizzaShop kind of pizza do you want?");
			return null;
		}
		IPizza pizza = null;
		if(type.equals("cheese")){
			pizza = new ShenZhenPizzaCheese();
		}else if(type.equals("fruit")){
			pizza = new ShenZhenPizzaFruit();
		}else if(type.equals("banana")){
			pizza = new ShenZhenPizzaBanana();
		}
		return pizza;
	}

}

  2.進一步說明:

  (1)做到了解耦--orderPizza()是在PizzaShop中定義的,但是他在使用createPizza()創建的pizza對象類執行prepare、bake、cut、box方法時並不知道具體的pizza對象是哪種類型。

  (2)pizza對象的具體類型僅由具體的pizza店(顧客)決定。

  3.有關工廠方法

  (1)簡單工廠是有一個專職對象負責所有具體類的實例化,而工廠方法則是由一羣子類來負責實例化;

  (2)將一個orderpizza方法和一個工廠方法聯合起來,可以成爲一個框架;

  (3)工廠方法將生產知識封裝進各個創建者,這種做法也可視爲一個框架;

  4.定義工廠方法模式

  (1)工廠方法模式定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。工廠方法讓類把實例化推遲到子類。

 


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