什么是工厂方法模式?

工厂方法模式是一种创建型设计模式,它定义了一个用于创建对象的接口(工厂方法),但让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
简单来说,它提供了一种封装对象创建过程的方式,将实际的对象创建逻辑推迟到子类中进行。

核心思想

想象一下,你有一个类需要创建一个产品对象,但具体创建哪种产品在编写该类时并不确定,或者希望由子类来决定。这时,你可以在父类中定义一个抽象的“工厂方法”,该方法返回一个产品类型的对象。然后,在不同的子类中实现这个工厂方法,让每个子类根据自身需求创建并返回具体的产品实例。

优点

  1. 解耦 (Decoupling):
    1. 将产品的创建逻辑从使用产品的代码(客户端)中分离出来。
    2. 客户端只需要知道产品的抽象接口,而不需要关心具体的实现类是如何被创建的。
    3. 同时,创建者(父类)也只依赖于产品接口。
  1. 灵活性和可扩展性 (Flexibility & Extensibility):
    1. 遵循“开闭原则”(Open/Closed Principle)。
    2. 当需要引入新的产品类型时,只需要添加新的具体产品类和对应的具体工厂子类,而无需修改现有的工厂父类或客户端代码。
  1. 单一职责原则 (Single Responsibility Principle):
    1. 将对象创建的逻辑集中到工厂方法或具体的工厂子类中,使得代码结构更清晰,职责更明确。

使用场景

  1. 当一个类不知道它所必须创建的对象的类时。
  1. 当一个类希望由它的子类来指定它所创建的对象时。
  1. 当你希望将创建对象的逻辑局部化,以便在未来更容易修改或替换时。
  1. Android 中的场景:
      • 创建不同类型的 ViewModel:ViewModelProvider.Factory 就是工厂方法模式的一个典型应用,它允许你自定义 ViewModel 的创建过程,特别是需要传递参数或依赖注入时。
      • 根据不同的条件或配置创建不同类型的 Fragment 或 Dialog。
      • 在自定义 RecyclerView.Adapter 中,根据 viewType 创建不同类型的 ViewHolder(虽然 onCreateViewHolder 更接近抽象工厂的变体,但其“延迟到子类决定具体类型”的思想与工厂方法类似)。
      • 提供库或框架给用户使用时,允许用户通过实现工厂方法来扩展或替换某些组件的创建。

UML图

下面是工厂方法模式的一个典型 UML 结构图,以我们稍后将要实现的“日志记录器”为例:
  • Logger (Product): 定义了日志记录器对象的接口。
  • FileLogger, DatabaseLogger, ConsoleLogger (ConcreteProduct): 则是实现了 Logger 接口的具体产品类。
  • LoggerFactory (Creator): 声明了工厂方法 createLogger(),它返回一个 Logger 对象。LoggerFactory 也可以定义一个使用 Logger 对象的方法,如 logMessage()。
  • FileLoggerFactory, DatabaseLoggerFactory, ConsoleLoggerFactory (ConcreteCreator): 实现了 createLogger() 方法,以返回具体日志记录器的实例。

代码示例

日志记录器示例

在这个例子中:
  • 客户端代码 (main 函数) 决定使用哪个工厂 (FileLoggerFactory, DatabaseLoggerFactory, etc.)。
  • 客户端通过调用工厂的 logMessage 方法来记录日志。
  • logMessage 方法内部调用了抽象的 createLogger 方法,具体由哪个子工厂实现,就创建哪个具体的 Logger 实例。
  • 客户端代码与具体的 Logger 实现(FileLogger, DatabaseLogger)完全解耦,只依赖于 LoggerFactory 和 Logger 接口。

Android ViewMode示例

总结

  • 工厂方法模式通过将对象创建过程延迟到子类,有效地解耦了对象的创建和使用,提高了系统的灵活性和可扩展性。
  • 当需要创建的对象类型可能变化,或者希望由子类来决定具体创建哪个对象时,工厂方法模式是一个非常好的选择。
  • 理解并运用工厂方法模式,可以帮助我们更好地管理对象的创建,尤其是在处理依赖注入和复杂对象初始化时。
设计模式——创建型-抽象工厂模式设计模式——学习大纲