理解工廠模式


title: “理解工廠模式”

url: “https://wsk1103.github.io/

tags:

  • 設計模式

是什麼

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

創建型模式。在基類中定義一個創建對象的接口,並且讓子類選擇實例化哪個類。工廠方法允許類將實例化延遲到子類。

工廠模式的分類

  • Factory Method,工廠方法模式。
  • Abstract Factory,抽象工廠模式。

優缺點

優點:

解耦:把對象的創建和使用的過程分開。既只負責對象的創建,對象是怎麼使用的,就不關我的事了。
降低代碼的重複性:如果創建一個對象比較複雜,但是許多地方需要使用到對象,那麼就會有許多重複的代碼。
降低維護成本:由於工廠模式只負責對象的創建,所以當業務邏輯發生變化時,不需要修改所有創建該對象的類,只需要在創建的邏輯裏面修改即可。

工廠方法模式

在基類的編程中,工廠方法模式是一種創建型模式,它使用工廠方法來處理創建對象的問題,而無需指定確切的類。這是通過調用工廠方法創建對象來完成的,也就是在接口中指定並由子類實現,或者在基類中實現並由子類覆蓋,而不是通過調用構造函數。

例子

鐵匠鑄造兵器,精靈需要精靈類的兵器,並且獸人也需要獸人類的兵器。根據相應的種族選擇相應的鐵匠來鑄造兵器。

//鐵匠
public interface Blacksmith {
  Weapon manufactureWeapon(WeaponType weaponType);
}

//兵器
public interface Weapon {
    
}

//精靈兵器
public class ElfWeapon implements Weapon{
    
}

//獸人兵器
public class OrcWeapon implements Weapon{
    
}

//製作精靈兵器的鐵匠
public class ElfBlacksmith implements Blacksmith {
  public Weapon manufactureWeapon(WeaponType weaponType) {
    return new ElfWeapon(weaponType);
  }
}

//製作獸人兵器的鐵匠
public class OrcBlacksmith implements Blacksmith {
  public Weapon manufactureWeapon(WeaponType weaponType) {
    return new OrcWeapon(weaponType);
  }
}

現在根據需要選擇相應的鐵匠

//精靈
Blacksmith blacksmith = new ElfBlacksmith();
//兵器-槍
blacksmith.manufactureWeapon(WeaponType.SPEAR);
//兵器-盾
blacksmith.manufactureWeapon(WeaponType.SHIELD);
//獸人同理

應用

  • 一個類不知道它所需要的對象的類,在工廠模式中,客戶端不需要知道具體產品類的類名,只需要知道對應的工廠即可,具體的產品對象由具體的工廠創建,但是客戶端需要知道創建具體產品是哪個工廠類。
  • 一個類通過其子類來指定創建哪個對象,在工廠模式中,對於抽象工廠類只需要提供一個創建產品的接口,而由其子類來確定具體要創建哪個對象。
  • 將創建的對象委託給多個工廠子類的某一個,客戶端在使用時,不需要關心是哪一個工廠子類在創建產品子類,需要時動態指定,可以將具體的工廠類的類名存儲在配置文件或者數據庫中。

工廠方法模式角色分配

  • 抽象工廠角色:是工廠模式的核心,與應用程序無關。任何在模式中創建的對象的工廠類必須實現該接口。
  • 具體工廠角色:抽象工廠類的具體實現,包含着與應用程序相關的邏輯。
  • 抽象產品角色:產品對象的共同父類或共同擁有的接口。
  • 具體產品對象:實現了抽象產品角色所定義的接口。某具體產品有專門的具體工廠創建,它們之間往往一一對應

java中的應用

  • java.util.Calendar
  • java.util.ResourceBundle
  • java.text.NumberFormat
  • java.nio.charset.Charset
  • java.net.URLStreamHandlerFactory
  • java.util.EnumSet
  • javax.xml.bind.JAXBContext

抽象工廠模式

提供用於創建相關或從屬對象族的接口,而無需指定其具體類。

抽象工廠模式是工廠方法模式的進一步深化,在抽象工廠模式中,工廠類不僅可以創建一種產品,還能創建一組產品。

例子

現在有一組產品:城堡,國王,軍隊。

現在有2個國家:精靈和獸人。

//城堡
public interface Castle {
  String getDescription();
}
//國王
public interface King {
  String getDescription();
}
//軍隊
public interface Army {
  String getDescription();
}

//精靈的實現
// Elven implementations ->
public class ElfCastle implements Castle {
  static final String DESCRIPTION = "This is the Elven castle!";
  @Override
  public String getDescription() {
    return DESCRIPTION;
  }
}
public class ElfKing implements King {
  static final String DESCRIPTION = "This is the Elven king!";
  @Override
  public String getDescription() {
    return DESCRIPTION;
  }
}
public class ElfArmy implements Army {
  static final String DESCRIPTION = "This is the Elven Army!";
  @Override
  public String getDescription() {
    return DESCRIPTION;
  }
}

//獸人的實現同理
// Orcish implementations similarly...

接下來精靈和獸人王國將要包含城堡,國王,軍隊。

//王國工廠
public interface KingdomFactory {
  Castle createCastle();
  King createKing();
  Army createArmy();
}

//精靈王國
public class ElfKingdomFactory implements KingdomFactory {
  public Castle createCastle() {
    return new ElfCastle();
  }
  public King createKing() {
    return new ElfKing();
  }
  public Army createArmy() {
    return new ElfArmy();
  }
}

//獸人王國
public class OrcKingdomFactory implements KingdomFactory {
  public Castle createCastle() {
    return new OrcCastle();
  }
  public King createKing() {
    return new OrcKing();
  }
  public Army createArmy() {
    return new OrcArmy();
  }
}

工廠有了,現在開始建造精靈王國

KingdomFactory factory = new ElfKingdomFactory();
Castle castle = factory.createCastle();
King king = factory.createKing();
Army army = factory.createArmy();

castle.getDescription();  // Output: This is the Elven castle!
king.getDescription(); // Output: This is the Elven king!
army.getDescription(); // Output: This is the Elven Army!

此外,我們還可以設計不同的工廠來實現不同的具體工廠。
通過枚舉和switch來區分具體工廠實現。

public static class FactoryMaker {

  public enum KingdomType {
    ELF, ORC
  }

  public static KingdomFactory makeFactory(KingdomType type) {
    switch (type) {
      case ELF:
        return new ElfKingdomFactory();
      case ORC:
        return new OrcKingdomFactory();
      default:
        throw new IllegalArgumentException("KingdomType not supported.");
    }
  }
}

public static void main(String[] args) {
  App app = new App();

  LOGGER.info("Elf Kingdom");
  app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
  LOGGER.info(app.getArmy().getDescription());
  LOGGER.info(app.getCastle().getDescription());
  LOGGER.info(app.getKing().getDescription());

  LOGGER.info("Orc Kingdom");
  app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
  -- similar use of the orc factory
}

應用

  • 和工廠方法一樣客戶端不需要知道它所創建的對象的類
  • 需要一組對象共同完成某種功能時,並且可能存在多組對象完成不同功能的情況。(同屬於同一個產品族的產品)
  • 系統結構穩定,不會頻繁的增加對象。(因爲一旦增加就需要修改原有代碼,不符合開閉原則)

工廠方法模式角色分配

  • 抽象工廠角色:是工廠模式的核心,與應用程序無關。任何在模式中創建的對象的工廠類必須實現該接口。
  • 具體工廠角色:抽象工廠類的具體實現,包含着與應用程序相關的邏輯。
  • 抽象產品角色:產品對象的共同父類或共同擁有的接口。
  • 具體產品對象:實現了抽象產品角色所定義的接口。在抽象工廠中創建的產品屬於同一產品族,這不同於工廠模式中的工廠只創建單一產品。

java中的應用

javax.xml.parsers.DocumentBuilderFactory
javax.xml.transform.TransformerFactory
javax.xml.xpath.XPathFactory

參考

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