Java設計模式-工廠模式

簡單來說工廠模式就是幫助我們創建對象,隱藏了對象創建過程的複雜度(如類B需要調用類A,工廠類提供A類的創建接口,B只需要調用接口傳入相應參數即可)、避免你辛苦的準備構造方法的參數。說白了–就是工廠提供產品給客戶(按照提供的方式不同分成三類:簡單工廠、工廠、抽象工廠) 具體簡介看下面:

工廠模式是我們最常用的實例化對象模式了,是用工廠方法代替new操作的一種模式。著名的Jive論壇 ,就大量使用了工廠模式,工廠模式在Java程序系統可以說是隨處可見。因為工廠模式就相當於創建實例對象的new,我們經常要根據類Class生成實例對象,如A a=new A() 工廠模式也是用來創建實例對象的,所以以後new時就要多個心眼,可以考慮是否使用工廠模式,雖然這樣做,可能多做一些工作,但會給你系統帶來更大的可擴展性和盡量少的修改量

角色

工廠模式有以下幾個角色(結合下面流程圖理解),產品即需要創建的實例對象

  • 抽象產品類:所創建產品的父類,給出一個抽象接口或抽象類,以及一般由具體產品類具體實現。(多態的表現)— 如 Animal
  • 具體產品類:抽象產品類的實現類,為實現某個具體產品的對象。 — 如 Dog
  • 抽象工廠類:工廠提供創建產品的方法、工廠方法模式的核心(簡單工廠模式無此抽象類),與應用程序無關。是具體工廠必須實現的接口或者必須繼承的父類。
  • 具體工廠類:繼承抽象工廠類,實現具體業務邏輯。

工廠模式和抽象工廠模式

圖解工廠模式和抽象工廠模式流程對比

工廠模式

抽象工廠模式

簡單工廠模式(靜態工廠方法)

含義:沒有抽象工廠類,由工廠類自身提供產品,代碼如下

抽象產品類(抽象類或接口)

public interface IProduct{      void method();  }

具體產品實現類

//A產品  public class ProductA implement IProduct{      void method(){          logger.info("ProductA");      }  }    //B產品  public class ProductB implement IProduct{      void method(){          logger.info("ProductB");      }  }

工廠類

public class Factory{      //簡單工廠模式 只有一個靜態方法提供產品所以也叫靜態工廠方法      public static IProduct createProduct(String productName){          if("A".equals("A"){              return new ProductA();          }else if("B".equals("B"){              return new ProductB();          }else      }  }
  • 優點: 強調職責單一原則,一個類只提供一種功能
  • 缺點: 一旦對工廠類修改就違反了開閉原則

工廠模式

工廠模式有一個抽象工廠類對應多個具體工廠實現類、一個抽象產品類對應一個具體實現類、並且每個具體工廠類只能創建一個具體產品類的實例

抽象產品類(抽象類或接口)

public interface IProduct{      void method();  }

具體產品實現類

//A產品  public class ProductA implement IProduct{      void method(){          logger.info("ProductA");      }  }    //B產品  public class ProductB implement IProduct{      void method(){          logger.info("ProductB");      }  }

抽象工廠類(抽象類或接口)

public abstract class Factory{  /**  *抽象工廠方法  *具體產生什麼由子類決定  *@return 具體產品對象  */  public abstract IProduct createProduct();  }     

具體工廠類

//A工廠  public class AFactory extends Factory {      //提供A產品      public  IProduct createProduct(){          return new ProductA();       }  }    //B工廠  public class BFactory extends Factory {      //提供B產品      public  IProduct createProduct(){          return new ProductB();       }  }

用法

Factory factory = new AFactory();  IProduct aProduct = factory.createProduct();  product.method();  
  • 優點:克服了簡單工廠違背開放-封閉原則的缺點,又保留了封裝對象創建過程的優點,降低客戶端和工廠的耦合性,所以說「工廠模式」是「簡單工廠模式」的進一步抽象和推廣
  • 缺點:每增加一個產品,相應的也要增加一個子工廠,加大了額外的開發量。

抽象工廠模式

工廠模式有一個抽象工廠類對應多個具體工廠實現類、多個抽象產品類對應多個具體實現類、並且每個具體工廠類可以創建多個具體產品類的實例。

抽象產品類(抽象類或接口)

//飲料  public interface IDrink{      void method();  }  //食物  public interface IFood{      void method();  }

具體產品實現類

//麵條  public class Noddle implement IFood{      void method(){          logger.info("麵條");      }  }    //米飯  public class Rice implement IFood{      void method(){          logger.info("米飯");      }  }    //可樂  public class Cola implement IDrink{      void method(){          logger.info("可樂");      }  }    //米飯  public class Sprite implement IDrink{      void method(){          logger.info("雪碧");      }  }

抽象工廠類(抽象類或接口)

public abstract class Factory{  /**  *抽象工廠方法  *具體產生什麼由子類決定  *@return 具體產品對象  */  public abstract IFood createFoodProduct();  public abstract IDrink createDrinkProduct();  }     

具體工廠類

//A餐工廠(提供可樂和米飯)  public class AFactory extends Factory{      //提供可樂      public  IDrink createDrinkProduct(){          return new Cola();       }         //提供米飯      public  IFood  createFoodProduct(){          return new Rice();       }  }    //B餐工廠(提供麵條和雪碧)  public class BFactory extends Factory{      //提供麵條      public  IFood createFoodProduct(){          return new Noddle();       }     //提供雪碧      public  IDrink createDrinkProduct(){          return new Sprite();       }  }

用法

Factory factory = new AFactory();  IDrink cola = factory.createDrinkProduct();  cola.method();  IFood riceFood = factory.createFoodProduct();  riceFood.method();  
  • 優點
    1. 具有工廠方法模式解耦的優點。
    2. 工廠模式針對的是一個產品等級結構,抽象工廠模式針對的是面向多個產品等級結構的。 最主要的是可以在類內部對產品族的關聯關係進行定義和描述。
  • 缺點
    1. 產品族的擴展將是一件十分費力的事情,假如產品族中需要增加一個新的產品,則幾乎所有的工廠類都需要進行修改。
    2. 在具體工廠類的方法中,對於產品族裡的產品,只能使用其中一個。這也比較容易理解,比如,一個套餐不會包含兩款飲料(一款車子不可以搭載兩種空調)。

總結

有利有弊

優點:將對象的創建統一起來便於維護和整體把控,對擴展開放,對修改封閉 缺點:耦合性提高,由於工廠類集中了所有實例的創建邏輯,違反了高內聚責任分配原則,將全部創建邏輯集中到了一個工廠類中,這種對條件的判斷和對具體產品類型的判斷交錯在一起,很難避免模塊功能的蔓延,對系統的維護和擴展非常不利。

使用有限

從工廠模式的示例可以看出:工廠模式需要類實現它的接口並且在業務內部存在明顯的繼承關係,比如汽車和奔馳寶馬的關係。而繼承關係往往存在於模型之間,業務之間很難存在繼承關係,因此如果業務內部或者業務之間沒有這種顯式的繼承關係該咋辦?就算業務內部有繼承關係,各個業務交給你統一管理,這樣就會提高代碼的耦合性,當創建邏輯複雜的時候,工廠方法就很複雜,容易產生干擾。

其開閉性優點很容易被替代

可以通過高度層次化和模塊化來提高系統的開閉性,而不必生硬地去套用工廠模式。