设计模式之美笔记 —— 工厂模式

设计模式之美 - 44

工厂模式分为三种:

目录

一、简单工厂模式(将所有的创建逻辑都放在一个工厂类中)

二、工厂方法模式(将复杂的逻辑拆分到多个工厂类中)

三、抽象工厂

四、依赖注入框架的设计与实现

五、判断是否需要使用工厂类的标准


问题:

  • 什么时候该用工厂模式?
  • 相对于直接 new 来创建对象,用工厂模式来创建究竟有什么好处呢? 

    面试问题:有哪些创建对象的方式

一、简单工厂模式(将所有的创建逻辑都放在一个工厂类中)

如以下代码所示:这个类只负责对象的创建。这个类就是 简单工厂模式类

public class RuleConfigParserFactory {
  public static IRuleConfigParser createParser(String configFormat) {
    IRuleConfigParser parser = null;
    if ("json".equalsIgnoreCase(configFormat)) {
      parser = new JsonRuleConfigParser();
    } else if ("xml".equalsIgnoreCase(configFormat)) {
      parser = new XmlRuleConfigParser();
    } else if ("yaml".equalsIgnoreCase(configFormat)) {
      parser = new YamlRuleConfigParser();
    } else if ("properties".equalsIgnoreCase(configFormat)) {
      parser = new PropertiesRuleConfigParser();
    }
    return parser;
  }
}

该方法使得我们每次需要一个对象的时候,都要进行创建,这样并不利于对象的复用,可以通过以下方法来达到节省内存和对象创建时间的目的。可以将 parser 事先创建好缓存起来。使用的时候直接取出即可。类似是单例模式和简单工厂模式的结合。

public class RuleConfigParserFactory {
  private static final Map<String, RuleConfigParser> cachedParsers = new HashMap<>();

  static {
    cachedParsers.put("json", new JsonRuleConfigParser());
    cachedParsers.put("xml", new XmlRuleConfigParser());
    cachedParsers.put("yaml", new YamlRuleConfigParser());
    cachedParsers.put("properties", new PropertiesRuleConfigParser());
  }

  public static IRuleConfigParser createParser(String configFormat) {
    if (configFormat == null || configFormat.isEmpty()) {
      return null;//返回null还是IllegalArgumentException全凭你自己说了算
    }
    IRuleConfigParser parser = cachedParsers.get(configFormat.toLowerCase());
    return parser;
  }
}

以上两种实现方式,如果我们需要增加新的对象类型的时候,那么势必要修改代码,稍微不符合 开闭原则 。

二、工厂方法模式(将复杂的逻辑拆分到多个工厂类中)

简单工厂类第一种代码实现中,有一组 if 分支判断逻辑,是不是应该用多态或其他设计模式来替代呢?

下面代码中使用了多态,代替了if分支判断逻辑:


public interface IRuleConfigParserFactory {
  IRuleConfigParser createParser();
}

public class JsonRuleConfigParserFactory implements IRuleConfigParserFactory {
  @Override
  public IRuleConfigParser createParser() {
    return new JsonRuleConfigParser();
  }
}

public class XmlRuleConfigParserFactory implements IRuleConfigParserFactory {
  @Override
  public IRuleConfigParser createParser() {
    return new XmlRuleConfigParser();
  }
}

public class YamlRuleConfigParserFactory implements IRuleConfigParserFactory {
  @Override
  public IRuleConfigParser createParser() {
    return new YamlRuleConfigParser();
  }
}

public class PropertiesRuleConfigParserFactory implements IRuleConfigParserFactory {
  @Override
  public IRuleConfigParser createParser() {
    return new PropertiesRuleConfigParser();
  }
}

实际上,这就是工厂方法模式的典型代码实现。这样当我们新增一种 parser 的时候,只需要新增一个实现了 IRuleConfigParserFactory 接口的 Factory 类即可。所以,工厂方法模式比起简单工厂模式更加符合开闭原则。

但是:

  • 每个 Factory 类只是做简单的 new 操作,功能非常单薄(只有一行代码),也没必要设计成独立的类,所以,在这个应用场景下,简单工厂模式简单好用,比工厂方法模式更加合适。
  • 当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。

工厂方法模式和简单工厂模式在订单系统中的应用

三、抽象工厂

可以让一个工厂负责创建多个不同类型的对象

 

四、依赖注入框架的设计与实现
 

五、判断是否需要使用工厂类的标准

  1. 封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对调用者透明。
  2. 代码复用:创建代码抽离到独立的工厂类之后可以复用。
  3. 隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象。
  4. 控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值