# 抽象工厂模式

# 参考

  1. 抽象工厂模式 (opens new window)
  2. 抽象工厂模式(详解版) (opens new window)
  3. 工厂方法模式比较 (opens new window)

# 定义

简单工厂、工厂方法模式都是用于同一类型对象的创建,比如冰箱厂只生产冰箱、空调厂只生产空调。

然而在实际生活中,许多工厂是综合性工厂,比如格力,既生产格力冰箱,也生产格力空调等等。

抽象工厂模式,就是访问者无需指定具体的产品类,就能够创建、获取同一系列、族群相关的产品,比如我要格力家电,那么格力工厂就会把格力冰箱、空调、电视等等给我。

抽象工厂模式与工厂方法模式的不同在于,工厂方法模式生产一种类型的产品,而抽象工厂模式用于生产多个属于同一系列的产品。

# 应用场景

代码中有多个不同系列的相关产品交互,由于无法提前获取客户端需要的系列,或者考虑到可扩展性,这种情况下可以使用抽象工厂模式。

比如:一个GUI应用,在windows和mac系统下都需要渲染button、dialog等组件,但是在不同的平台下组件的样式为了适应平台特性,都有所差异。

此时可以使用抽象工厂模式,提炼抽象工厂,以及不同平台下对应的工厂,来生产同一系列的产品。

# 实现、应用思路

给所有产品根据系列归类。

  1. 抽象工厂,提供、定义创建产品的通用接口。

  2. 具体工厂,实现抽象工厂的抽象方法,完成同系列具体产品的创建。

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

  4. 具体产品,实现了抽象产品定义的接口,由具体工厂来创建,与具体工厂是多对一的关系,一个工厂创建同一系列的多个产品。

# 优点

  1. 可以确保同一类型产品的生产,匹配。

  2. 新增产品或者新增工厂,修改、新增工厂即可,无需修改外部业务逻辑,满足开闭原则。

  3. 统一类的产品由同一工厂管理,满足单一责职原则。

# 缺点

  1. 引入了众多的类、接口,增加了系统的抽象度,可能会更加难以理解。

# 代码实例

// 抽象产品
interface IButton {
  render(): void
}
interface IDialog {
  render(): void
}
// 同系列的具体产品
class WinButton implements IButton {
  render() {
    console.log('render windows button.')
  }
}
class WinDialog implements IDialog {
  render() {
    console.log('render windows dialog.')
  }
}
// 同系列的具体产品
class MacButton implements IButton {
  render() {
    console.log('render mac button.')
  }
}
class MacDialog implements IDialog {
  render() {
    console.log('render mac dialog.')
  }
}
// 抽象工厂
abstract class GUIFactory {
  abstract createButton(): IButton
  abstract createDialog(): IDialog
  render() {
    this.createButton().render()
    this.createDialog().render()
  }
}

// 具体工厂
class WindowsFactory extends GUIFactory {
  createButton(): WinButton {
    return new WinButton()
  }
  createDialog(): WinDialog {
    return new WinDialog()
  }
}
class MacFactory extends GUIFactory {
  createButton(): MacButton {
    return new MacButton()
  }
  createDialog(): MacDialog {
    return new MacDialog()
  }
}
// windows平台下的GUI渲染
new WindowsFactory().render()
// mac平台下的GUI渲染
new MacFactory().render()
上次更新: 12/13/2020, 9:01:56 AM