設計模式(2)-工廠方法模式詳解(易懂)

秦子帥發表於2017-12-29

工廠方法模式的定義

工廠方法模式(FACTORY METHOD)是一種常用的物件建立型設計模式,此模式的核心精神是封裝類中不變的部分,提取其中個性化善變的部分為獨立類,通過依賴注入以達到解耦、複用和方便後期維護擴充的目的。它的核心結構有四個角色,分別是抽象工廠;具體工廠;抽象產品;具體產品。

image
從上面的圖可以看出:Product為抽象產品類,負責產品的共性;Creator為抽象建立類;而具體的產品(ConcreteProduct)是由實現工廠ConcreteCreator完成的。 工廠方法模式詳解及舉例

一.首先先用程式碼解釋一下上面的圖:

1.抽象產品類

public abstract class Product {  
   //所有產品類的公共業務方法  
   public void method1() {  
       //公共方法的實現  
   }  

   //宣告抽象業務方法  
   public abstract void method2();  
}
複製程式碼

2.具體產品類

public class ConcreteProduct1 extends Product{  
   //實現業務方法  
   public void method2() {  
       //業務方法的實現  
   }  
}

public class ConcreteProduct2 extends Product{  
   //實現業務方法  
   public void method2() {  
       //業務方法的實現  
   }  
}
複製程式碼

3.抽象工廠類

public abstract class Creator{  

 //  public abstract Product createProduct(String arg);
public abstract <T extends Product> T createProduct(Class<T> c);
}
複製程式碼

4.具體工廠類

public class ConcreteCreator extends Creator{  

public <T extends Product> T createProduct(class<T> c){
Product product=null;
try{
      product =(T)Class.forName(c.getName()).newInstance();
}catch (Exception e){
   
}
return (T)product;
}

}
複製程式碼

5呼叫:

       Creator creator=new ConcreteCreator();
       Product product=creator.createProduct(ConcreteProduct1.class);
      // product.method2();
複製程式碼

根據上面的程式碼應該看懂了吧?如果不懂下面我具體舉個例子:

二.舉例

我們拿手機舉例,一個手機工廠生產兩種手機,分別是華為手機和小米手機。過程就是在工廠經過一系列的加工製作生產出這兩種手機,下面用程式碼來演示一下:

1.抽象產品類,也就是兩種手機的共性:

定義了兩個方法,一個是打電話,一個是手機的品牌,兩種手機的品牌是不同的,所以是抽象的。

public abstract class Phone {
   //兩種手機都可以打電話
   public void Call() {
       //公共方法的實現
   }

   //兩種手機都有品牌,但是品牌不同,所以是抽象的
   public abstract void PhoneBrand();
}
複製程式碼

2.具體的產品類, 就是華為手機和小米手機兩個產品

public class HUAWEIPhone extends Phone {
   //品牌
   @Override
   public void PhoneBrand() {
       Log.e("qzs","我的品牌是華為");
   }
}

public class MIPhone extends Phone {
   //品牌
   @Override
   public void PhoneBrand() {
       Log.e("qzs","我的品牌是小米");
   }
}
複製程式碼

3.抽象工廠類,要想生產手機就必須要有工廠,所以先要定義生產手機的抽象方法。

public abstract class PhoneFactory  {
   public abstract <T extends Phone> T createPhone(Class<T> c);
}
複製程式碼

4.具體工廠類,具體的生產手機的方法

public class ConcretePhoneFactory extends PhoneFactory {

   @Override
   public <T extends Phone> T createPhone(Class<T> c) {
       Phone phone=null;
       try{
           phone =(Phone)Class.forName(c.getName()).newInstance();
           Log.e("qzs","生產了一個手機");
           phone.PhoneBrand();
       }catch (Exception e){

       }
       return (T) phone;
   }
}
複製程式碼

呼叫:

       PhoneFactory phoneFactory=new ConcretePhoneFactory();
       Phone huaiweiphone=phoneFactory.createPhone(HUAWEIPhone.class);
       Phone miphone=phoneFactory.createPhone(MIPhone.class);
複製程式碼

執行的結果如下,可以看到生產了兩種手機,這次工廠方法模式是不是有了更為清楚的認識。


工廠方法模式不同形式

1.簡單工廠模式

就是把抽象工廠類去掉,具體工廠類的方法上加上static,拿上面的例子說明:

public class ConcretePhoneFactory {

   public  static <T extends Phone> T createPhone(Class<T> c) {
       Phone phone=null;
       try{
           phone =(Phone)Class.forName(c.getName()).newInstance();
           Log.e("qzs","生產了一個手機");
           phone.PhoneBrand();
       }catch (Exception e){
       }
       return (T) phone;
   }
}
複製程式碼

2.多工廠方法模式

從名字就可以看出來,是有多個具體工廠類,上面的例子是兩種手機都放在了一個工廠了,現實的話應該在兩個工廠生產,也就是多工廠方法模式。

分成兩個工廠後,抽象工廠類就不用傳參了,因為每種手機都有自己工廠了。

修改後的抽象工廠類:

public abstract class PhoneFactory  {
   public abstract  Phone createPhone();
}
複製程式碼

修改的具體工廠類:

public class ConcreteHUAWEIFactory extends PhoneFactory {
   @Override
   public Phone createPhone() {
       Log.e("qzs","生產了一個華為手機");
       return new HUAWEIPhone();
   }
}

public class ConcreteMIFactory extends PhoneFactory {
   @Override
   public Phone createPhone() {    
       Log.e("qzs","生產了一個小米手機");
       return new MIPhone();
   }
}
複製程式碼

3.工廠方法模式來實現單例模式

單例模式的核心要求就是在記憶體中只有一個物件,通過工廠方法模式也可以只在記憶體中生產一個物件。

public class Singleton {  
 
   private Singleton() {  
 
   }  
 
   public void doSomething() {  
       System.out.println("具體邏輯");  
   }  
}
複製程式碼

通過獲得類構造器,然後設定訪問許可權,生成一個物件,然後提供外部訪問,保證記憶體中的物件唯一。

public class SingletonFactory {  
 
   private static Singleton singleton;  

   static {  
       try {  
           Class clazz = Class.forName(Singleton.class.getName());  
           Constructor constructor = clazz.getDeclaredConstructor();  
           constructor.setAccessible(true);  
           singleton = (Singleton) constructor.newInstance();  
       } catch (Exception e) {  
 
       }
   }  
 
   public static Singleton getSingleton() {  
 
       return singleton;  
   }  
}

複製程式碼

呼叫:

       Singleton singleton = SingletonFactory.getSingleton();  
       Singleton singleton2 = SingletonFactory.getSingleton();  
       System.out.println(singleton);  
       System.out.println(singleton2);
複製程式碼

列印後發現物件是相同的。

4.延遲初始化

一個物件被消費完畢後,並不立刻釋放,工廠類保持其初始狀態,等待再次被使用。


工廠方法模式優缺點

1.優點

工廠方法模式是完全符合開閉原則的;

工廠模式是一種典型的解耦模式,可以降低物件之間的耦合度;

工廠模式是依靠抽象架構的,它把例項化產品的任務交由實現類完成,擴充套件性比較好。

可以使程式碼結構清晰,有效地封裝變化。

對呼叫者遮蔽具體的產品類。如果使用工廠模式,呼叫者只關心產品的介面就可以了,至於具體的實現,呼叫者根本無需關心。即使變更了具體的實現,對呼叫者來說沒有任何影響。
複製程式碼

2.缺點

簡單的物件應用時,不適合工廠方法模式。


模式應用

工廠方法經常用在以下兩種情況中:

第一種情況是對於某個產品,呼叫者清楚地知道應該使用哪個具體工廠服務,例項化該具體工廠,生產出具體的產品來。Java Collection中的iterator() 方法即屬於這種情況。

第二種情況,只是需要一種產品,而不想知道也不需要知道究竟是哪個工廠為生產的,即最終選用哪個具體工廠的決定權在生產者一方,它們根據當前系統的情況來例項化一個具體的工廠返回給使用者,而這個決策過程這對於使用者來說是透明的。
複製程式碼

文章學習參考了《設計模式之禪》#

歡迎大家關注我的微信公眾號:安卓乾貨鋪

image

相關文章