工厂方法模式

参考

  1. 工厂方法模式
  2. 工厂方法模式(详解版)
  3. 工厂方法模式比较

定义

简单工厂模式违背了开闭原则,扩展的时候需要对工厂逻辑进行修改。

工厂方法模式是对简单工厂模式的进一步抽象化,多了一个抽象工厂。抽象工厂提供抽象的对象实例创建方法,具体由具体工厂来决定实例化的对象类型。

这样就可以在不修改原有代码的情况下对应用进行扩展,满足开闭原则。

应用场景

比如:一个 dialog 组件,为了适配不同平台下的 UI 风格,在 android、ios 下分别会渲染对应平台风格 button。

  1. 无法预知对象的确切类别,及其依赖关系,用户需要自由扩展。

    在上述场景中,button 对象的渲染可由具体工厂决定,这样当需要扩展的时候,只需要开发新的具体工厂子类, 重写创建 button 的对象的工厂方法即可。

  2. 用户不用关心产品创建的具体细节。

    比如在 dialog 组件中创建 button 的时候,会给 button 添加各种公共属性。 用户只需决定具体创建的 button 对象,或者可以使用默认的 button 对象,而无需关心 button 的其他创建细节。

实现、应用思路

  1. 抽象工厂,提供了创建产品的接口,可由具体工厂重写。

  2. 具体工厂,实现、重写抽象工厂中的抽象方法,决定产品的具体创建逻辑。

  3. 抽象产品(也可以是接口),定义了产品的具体规范,描述了产品的主要特性、功能。这是工厂模式的一大前提。

  4. 具体产品,实现了抽象产品定义的接口,由具体工厂来创建。

优点

  1. 避免了父类(高层模块)及其子类(子模块)的耦合。

  2. 单一职责原则,具体创建逻辑可放在子类中,更容易维护。

  3. 开闭原则,扩展只需要新增、修改子类即可。

缺点

如果类的个数过多,会导致代码复杂度、理解难度增加。

代码实例

const platforms = {
  android: 'android',
  ios: 'ios'
}

// 抽象产品(接口)
interface IButton {
  render(): void
}
// 抽象工厂
abstract class DialogFactory {
  abstract createButton(): IButton
  abstract platform: string
  render() {
    console.log(`Render on ${this.platform}.`)
    const button = this.createButton()
    button.render()
  }
}
// 具体产品
class IOSButton implements IButton {
  render() {
    console.log('Rendering ios button.')
  }
}
// 具体产品
class AndroidButton implements IButton {
  render() {
    console.log('Rendering android button.')
  }
}
// 具体工厂
class IOSDialogFactory extends DialogFactory {
  platform = platforms.ios
  createButton(): IButton {
    return new IOSButton()
  }
}
// 具体工厂
class AndroidDialogFactory extends DialogFactory {
  platform = platforms.android
  createButton(): IButton {
    return new AndroidButton()
  }
}

new IOSDialogFactory().render()
new AndroidDialogFactory().render()
上次更新: 4/23/2021, 4:07:56 PM