一.前言java
1.準備好開始烘烤某些鬆耦合的OO設計。編程
2.製造對象的方法除了new,還有不少其餘的方法;設計模式
3.初始化使用new常常會帶來一些耦合的問題,工廠模式能夠解決這個問題;框架
那麼「new」有什麼不對勁呢?
ide
其實,new沒有問題,有問題的是「改變」。則能夠用設計原則「找出會變化的部分,把他們從不變的部分分離出來」。測試
(即:將實例化具體類的方法抽離,或者封裝起來,使他們不會干擾其餘部分。)ui
4.重要原則--「針對接口編程」。spa
5.全部工廠模式都是用來封裝對象的建立。設計
二.披薩店實例--簡單工廠對象
1.pizza店有許多pizza類型,每種pizza從order開始的流程都要通過準備prepare、烘烤bake、切片cut和裝箱box,因此一般對於OO設計者們,初步能夠考慮到這樣的設計:
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。
//測試類 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的子類作決定建立具體的對象。
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)工廠方法模式定義了一個建立對象的接口,但由子類決定要實例化的類是哪個。工廠方法讓類把實例化推遲到子類。