JAVA设计模式之创建者模式中的三种工厂模式

工厂模式归属于设计模式中的创建者模式,其主要用途是为了让我们更加优雅的创建JAVA对象,常见的工厂模式主要分为简单工厂、工厂方法、抽象方法三种形式,具体使用中并不拘泥于形式。

JAVA设计模式之创建者模式中的三种工厂模式

所属分类: JAVA
专题标签: 设计模式 工厂 对象

前言

我们在实际写代码过程中往往不会过度强调在用哪种设计模式。
但了解学习优秀的设计模式能够便于我们写出更为优质的代码。
采用设计模式编写代码可以具备易用、拓展、清晰等多种特质。
既便如此,在实际编写过程中,不能被设计模式所束缚,因地制宜才是最好的。
本文主要讲述的是,创建者模式中的工厂模式。

模式介绍

创建者模式:为了用更加优雅的方式创建对象。
工厂模式:字如其意,用于创建对象的中心,主要为了生产出需要的对象。

简单工厂模式

该模式使用的频次较少,简单来说就是你需要什么,我创建什么。
该设计模式主要为了将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易。
简单工厂方法是静态方法,可通过工厂类类名直接调用,只需要传入一个简单的参数即可,无须知道对象的创建细节。
可以将参数保存在XML等格式的配置文件中,修改时无须修改任何Java源代码。
但是,工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则。

  1. //产品接口
  2. interface Person{
  3. void create();
  4. }
  5. //产品实现类
  6. public class Man implements Person {
  7. @Override
  8. public String create() {
  9. return "Create Man";
  10. }
  11. }
  12. public class Woman implements Person {
  13. @Override
  14. public String create() {
  15. return "Create Woman";
  16. }
  17. }
  18. //工厂类
  19. public class PersonFactory {
  20. public static Person create(String what)
  21. {
  22. Person person = null;
  23. switch (what)
  24. {
  25. case "M" :
  26. person = new Man();
  27. break;
  28. case "W" :
  29. person = new Woman();
  30. break;
  31. }
  32. return person;
  33. }
  34. }
  35. //最终调用
  36. Person man = PersonFactory.create("M");
  37. Person woman = PersonFactory.create("W");

优点:

  • 实现了对象创建和使用的分离
  • 一定程度上提高了系统的灵活性,对象使用者无需知晓创建对象的细节

缺点:

  • 工厂类集中了所有产品的创建逻辑,过度依赖工厂类,实际上提高了代码耦合度
  • 增加了系统的复杂度和理解难度
  • 系统扩展困难,添加新产品不得不修改工厂逻辑,重构频次过高
  • 使用静态工厂方法,工厂无法基于继承的等级结构,不能得到很好地扩展

场景:

  • 少类型的对象创建,不会造成工厂方法中的业务逻辑太过复杂
  • 使用者不想过多关心对象创建细节,想快速达成对象创建

工厂方法

工厂方法模式(Factory Method Pattern)简称工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式。
工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
工厂方法模式是简单工厂模式的进一步抽象和推广,保持了简单工厂模式的优点,并克服了它的缺点。
核心工厂类不再负责所有产品的创建,而是将具体创建工作交给其子类去完成,允许系统在不修改工厂角色的情况下引进新产品。
实际过程为:增加具体产品—>增加具体工厂,符合开闭原则。

  1. //产品接口
  2. interface Person{
  3. void create();
  4. }
  5. //产品实现类
  6. public class Man implements Person {
  7. @Override
  8. public String create() {
  9. return "Create Man";
  10. }
  11. }
  12. //以上与简单工厂一致
  13. //工厂方法父类(接口类)
  14. interface PersonFactory {
  15. Person createPerson();
  16. }
  17. //工厂方法子类(实现类)
  18. public class ManFactory implements PersonFactory {
  19. @Override
  20. public Person createPerson() {
  21. return new Man();
  22. }
  23. }
  24. //实际调用
  25. PersonFactory manFactory = new ManFactory();
  26. Person man = manFactory.createPerson();

优点:

  • 工厂方法用来创建客户所需要的产品,隐藏了哪种具体产品类将被实例化的细节
  • 自主选择需要使用的子类工厂,创建对象的细节封装在具体工厂内部
  • 在系统中加入新产品时,增加对应的子类(实现)工厂

缺点:

  • 一定程度上增加了系统的复杂度,会给系统带来一些额外的开销,增加了对应工厂类
  • 增加了系统的抽象性和理解难度

场景:

  • 使用者只需要知道所对应的工厂即可创建对象
  • 较多的细分产品类适用于工厂方法创建

抽象工厂模式

抽象工厂模式(Abstract Factory Pattern),提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类,抽象工厂模式又称为Kit模式。
抽象工厂模式中存在着产品族和产品等级两大概念。
产品族:同一个工厂生产的,位于不同产品等级结构中的一组产品,如下方代码的女人、女孩
产品等级:产品等级结构即产品的继承结构,如下方代码的女性->女人,女性->女孩

  1. //产品族 男性
  2. public interface Male {
  3. }
  4. //男性产品等级下男人
  5. public class Man implements Male {
  6. }
  7. //男性产品等级下男孩
  8. public class Boy implements Male {
  9. }
  10. //同理女性产品族
  11. public interface Female {
  12. }
  13. public class Woman implements Female {
  14. }
  15. public class Girl implements Female {
  16. }
  17. //抽象工厂
  18. interface PersonFactory {
  19. public Male createMale();
  20. public Female createFemale();
  21. }
  22. //实现工厂 成年生产工厂
  23. public class AdultFactory implements PersonFactory {
  24. @Override
  25. public Male createMale() {
  26. return new Man();
  27. }
  28. @Override
  29. public Female createFemale() {
  30. return new Woman();
  31. }
  32. }
  33. //实现工厂 幼年生产工厂
  34. public class ChildFactroy implements PersonFactory {
  35. @Override
  36. public Male createMale() {
  37. return new Boy();
  38. }
  39. @Override
  40. public Female createFemale() {
  41. return new Girl();
  42. }
  43. }
  44. //最终调用
  45. PersonFactory adultFactory = new AdultFactory();
  46. Male man = adultFactory.createMale();
  47. Female woman = adultFactory.createFemale();
  48. PersonFactory childFactory = new ChildFactroy();
  49. Male boy = childFactory.createMale();
  50. Female girl = childFactory.createFemale();

优点:

  • 使用者无需知晓具体对象的生成
  • 产品族中的多个对象被设计成一起工作时,能够保证使用者只使用同一个产品族中的对象
  • 增加新的产品族很方便,无须修改已有系统,符合开闭原则

缺点:

  • 当增加新的产品等级,需大改,甚至修改抽象层代码,重构成本高,违背了开闭原则

场景:

  • 系统不依赖于产品类实例如何被创建、组合和表达的细节
  • 系统中有多于一个的产品族,每次只使用其中某一产品族
  • 属于同一个产品族的产品将在一起使用时
  • 产品等级结构稳定,在设计完成之后不会向系统中增加新的产品等级结构或者删除已有的产品等级结构

备注

实际编写代码并不会局限于使用某一种设计模式。
代码在不断优化升级重构过程中会出现模式的迁移情况。
无论采用何种设计模式,编码时我们要考虑这些特质:

  • 逻辑清晰,模块划分合理
  • 可读性高
  • 健壮性高
  • 灵活,易扩展和易迁移。