JavaScript 设计模式 (三) 抽象工厂模式 Abstract factory pattern

356 阅读3分钟

定义

抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象,(例如:同属于一个品牌) 而无需指定其具体类。

个人理解

我有很多套方案,但是只要其中一套的某个或者某几个东西,并且它们是配套的(有一样的关联关系在里面),而且我并不关心具体怎么来的;

如果之前看过工厂方法模式,那么可以把这个看做工厂方法模式外边又套了一层工厂方法模式

流程图

抽象工厂流程图.png

代码示例

这里仅加了一个品牌来区分不同的工厂产品,实际应该是一个新的专属于对于工厂的类继承产品类之后,再返回专属于工厂的产品类

// 命名空间
namespace PeripheralFactory {
  export interface Brand { // 品牌接口
    brand?: string
  }
  interface MouseProps extends Brand { // 鼠标接口
    type: string
  }
  interface KeyboardProps extends Brand { // 键盘接口
    width: number
    height: number
    numberOfKeys: number
  }
  interface HeadphonesProps extends Brand { // 耳机接口
    microphone: boolean
    soundproof: boolean
  }

  export class Mouse { // 鼠标
    type: string = '有线'
    brand?: string
    constructor(props: MouseProps) {
      this.type = props.type
      this.brand = props.brand
    }
  }
  export class Keyboard { // 键盘
    width: number = 0 // 宽
    height: number = 0 // 高
    numberOfKeys: number = 0 // 键数
    brand?: string
    constructor(props: KeyboardProps) {
      this.width = props.width
      this.height = props.height
      this.numberOfKeys = props.numberOfKeys
      this.brand = props.brand
    }
  }
  export class Headphones { // 耳机
    microphone: boolean = true // 麦克
    soundproof: boolean = true // 隔音
    brand?: string
    constructor(props: HeadphonesProps) {
      this.microphone = props.microphone
      this.soundproof = props.soundproof
      this.brand = props.brand
    }
  }

  // 工厂
  export interface Factory   { 
    createMouse(props: MouseProps): Mouse // 创建鼠标
    createKeyboard(props: KeyboardProps): Keyboard  // 创建键盘
    createHeadphones(props: HeadphonesProps): Headphones // 创建耳机
  }

  // 罗技
  export class Logitech implements Factory {
    private brand: string = '罗技'
    
    // 创建鼠标
    createMouse(props: MouseProps): Mouse {
      props.brand = this.brand
      return new Mouse(props)
    }
    
    // 创建键盘
    createKeyboard(props: KeyboardProps): Keyboard {
      props.brand = this.brand
      return new Keyboard(props)
    }
    
    // 创建耳机
    createHeadphones(props: HeadphonesProps): Headphones {
      props.brand = this.brand
      return new Headphones(props)
    }
  }
  
  // 双飞燕
  export class A4TECH implements Factory {
    private brand: string = '双飞燕'
    
    // 创建鼠标
    createMouse(props: MouseProps): Mouse {
      props.brand = this.brand
      return new Mouse(props)
    }
    
    // 创建键盘
    createKeyboard(props: KeyboardProps): Keyboard {
      props.brand = this.brand
      return new Keyboard(props)
    }
    
    // 创建耳机
    createHeadphones(props: HeadphonesProps): Headphones {
      props.brand = this.brand
      return new Headphones(props)
    }
  }
  
  // 血手幽灵
  export class Bloody implements Factory {
    private brand: string = '血手幽灵'
    
    // 创建鼠标
    createMouse(props: MouseProps): Mouse {
      props.brand = this.brand
      return new Mouse(props)
    }
    
    // 创建键盘
    createKeyboard(props: KeyboardProps): Keyboard {
      props.brand = this.brand
      return new Keyboard(props)
    }
    
    // 创建耳机
    createHeadphones(props: HeadphonesProps): Headphones {
      props.brand = this.brand
      return new Headphones(props)
    }
  }
  
   // 雷蛇
  export class Razer implements Factory {
    private brand: string = '雷蛇'
    
    // 创建鼠标
    createMouse(props: MouseProps): Mouse {
      props.brand = this.brand
      return new Mouse(props)
    }
    
    // 创建键盘
    createKeyboard(props: KeyboardProps): Keyboard {
      props.brand = this.brand
      return new Keyboard(props)
    }
    
    // 创建耳机
    createHeadphones(props: HeadphonesProps): Headphones {
      props.brand = this.brand
      return new Headphones(props)
    }
  }
  
  // 模拟配置文件
  enum FACTORY_TYPE {
    TYPE = 'Logitech'
  }
  
  // 工厂列表
  export let FactoryList = {
    Logitech: () => new Logitech(),
    A4TECH: () =>  new A4TECH(),
    Bloody: () => new Bloody(),
    Razer: () => new Razer()
  }
  
  // 配合简单工厂使用
  export class Peripheral {
    static creatFactory() {
  
      // 读取配置并返回相应工厂
      return FactoryList[FACTORY_TYPE.TYPE]()
    }
  }
}

// 创建工厂
const Factory = PeripheralFactory.Peripheral.creatFactory()
// 使用工厂
let mouse = Factory.createMouse({ type: '有线' })
let keyboard = Factory.createKeyboard({ width: 100, height: 20, numberOfKeys: 208 })
let headphones = Factory.createHeadphones({ microphone: true, soundproof: true })
console.log(mouse, keyboard, headphones)

优缺点

  • 你可以确保同一工厂生成的产品相互匹配。
  • 你可以避免客户端和具体产品代码的耦合。
  • 单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
  • 开闭原则。 向应用程序中引入新产品变体时, 你无需修改使用处代码。
  • 添加新的工厂比较简单,但是添加产品比较复杂
  • 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。