前端设计模式:工厂模式(Factory)


00、基础概念

🚩工厂模式 封装了对象的创建new(),将消费者(使用)和生产者(实现)解耦。

工厂是干什么的?工厂是生产标准规格的商品的地方,建好工厂,投入原料(参数),产出特定规格的产品。so,工厂模式就是把对象的创建 ------ new() 封装起来,在工厂里实现对象的创建(商品的生产)。这样做的好处是用来解耦,解耦对象的消费(使用)和创建(实现),面向抽象编程(这个用到TS中的接口类型)。

✅使用场景

  • Vue中的createElement('h'); createElement('div')创建虚拟Dom;vue-router 中的路由基于模式mode创建不同的路由对象。
  • 多个同类对象的创建,创建过程复杂,而使用者不用关注创建、实现过程,只管拿到实例来使用。就像我们日常到超市购买商品,只管选择使用,不用关注商品是怎么生产的。

生产实例(商品)的工厂可以是小作坊,只生产少量简单的商品,也可以是大型的复杂工厂,因此基于场景复杂程度又有多个工厂模式:

类别 说明
简单工厂(Simple Factory) 小作坊,适用于少量对象的创建,集中式管理,使用简单、扩展不便
工厂方法(Factory Method) 正规小工厂,每种产品一个独立工厂,偏平化扩展
抽象工厂(Abstract Factory) 集团化大厂,产品种类、层级众多,需要多层级的工厂来管理,代码也稍复杂

实际掌握简单工厂就差不多了,工厂方法、抽象工厂了解下即可。


01、简单工厂(Simple Factory)

简单工厂模式,也称为静态工厂模式(Static Factory Method),由一个(静态)类统一管理对象的创建,,根据一个简单参数创建不同的示例对象。针对少量的、简单的场景,在工厂中统一实现所有商品的创建。如下示例,手机工厂提供多型号手机的创建,传入手机型号参数即可。

示例代码:

javascript 复制代码
let HuaweiPhone = class { name = '华为' }
let XiaomiPhone = class { name = '小米' }
// 手机生产工厂
class PhoneFactory {
  static create(type) {
    switch (type) {
      case 'huawei':
        return new HuaweiPhone()
      case 'xiaomi':
        return new XiaomiPhone()
      default:
        throw new Error(`不支持生产型号为${type}的设备`)
    }
  }
}
// 使用,调用工厂方法创建对象实例
let p1 = PhoneFactory.create('xiaomi')
let p2 = PhoneFactory.create('huawei')
console.log({ p1, p2 })

上面版本代码中,如果扩充其他型号,则需要修改工厂的代码,不利于扩展,可以稍微改进下,支持动态新增创建对象实例的方法。

javascript 复制代码
// 手机生产工厂
class PhoneFactory {
  // 实例对象创建器Map
  #constructors = new Map()
  constructor() {
    this.#constructors.set('huawei', () => new HuaweiPhone())
    this.#constructors.set('xiaomi', () => new XiaomiPhone())
  }
  // 可扩展型号
  add(type, func) {
    this.#constructors.set(type, func)
  }
  // 生产商品
  create(type) {
    const func = this.#constructors.get(type)
    if (func) {
      return func.call()
    }
    throw new Error(`不支持生产型号为${type}的设备`)
  }
}
const phoneFactory = new PhoneFactory()
// 添加苹果型号
let IPhone = class { name = '苹果' }
phoneFactory.add('iphone', () => new IPhone())
// 使用,调用工厂方法创建对象实例
let p1 = phoneFactory.create('iphone')
let p2 = phoneFactory.create('huawei')

02、工厂方法(Factory Method)

简单工厂是小作坊,产量有限,如果生产的型号很多,在一个地方管理所有的new() 操作,负担很大,风险也很大。工厂方法(也叫工厂模式)就是为每一个产品建立单独的工厂,一个工厂只生产一类商品,这样就可以灵活扩展,相互不影响了。

代码示例:

javascript 复制代码
let HuaweiPhone = class { name = '华为' }
let XiaomiPhone = class { name = '小米' }

// 没什么用的工厂基类(JS中可以不要),用来抽象工厂接口
let IFactory = class { creat() { } }
// 华为手机工厂
class HuaweiFactory extends IFactory {
  creat() {
    return new HuaweiPhone()
  }
}
// 小米手机工厂
class XiaomiFactory extends IFactory {
  creat() {
    return new XiaomiPhone()
  }
}
// 使用
const huaweiFactory = new HuaweiFactory()
let p1 = huaweiFactory.creat()
let p2 = huaweiFactory.creat()

在Java、C#语言中都会用接口进行抽象、约束,面向抽象编程,实现起来会比较清晰。JavaScript中就没法抽象约束了,比较随意,只能靠TypeScript了。


03、抽象工厂(Abstract Factory)

如果说简单工厂是小作坊,工厂方法就是小工厂,那抽象工厂就是大型集团了,下属多个产业链、多个工厂。

抽象工厂可以看做是简单工厂+工厂方法的结合升级,增加了产品族的概念。还是用电子产品生产来举例,比如一个大型电子产品工厂,有多个品牌产品,如华为、小米,每个品牌的电子产品形成一个产品族,包含多个产品,如手机、平板、电视等等,不同品牌的产品也是不同的。因此一个产品工厂(如华为工厂)就会有多条生产线,生产多个产品(手机、平板、电视)。

🚩基本结构:抽象工厂类+具体工厂类,抽象产品类+具体产品类组合。JS中没有没有抽象类、接口的概念,只能示意一下(或者TS),抽象工厂简单了解即可,掌握上面的简单工厂、工厂方法就差不多了。

示例代码:

javascript 复制代码
// 模拟手机抽象类
let IPhone = class { name = '手机' }
// 手机产品
let HuaweiPhone = class extends IPhone { name = '华为' + this.name }
let XiaomiPhone = class extends IPhone { name = '小米' + this.name }

// 模拟电视抽象类
let ITV = class { name = '电视' }
// 电视产品
let HuaweiTV = class extends ITV { name = '华为' + this.name }
let XiaomiTV = class extends ITV { name = '小米' + this.name }

// 模拟抽象工厂,含两个抽象方法,生产手机、电视
let AbstractFactory = class { createPhone() { }; createTV() { } }
// 具体工厂:华为工厂
class HuaweiFactory extends AbstractFactory {
  createPhone() {
    return new HuaweiPhone()
  }
  createTV() {
    return new HuaweiTV()
  }
}
// 具体工厂:小米工厂
class XiaomiFactory extends AbstractFactory {
  createPhone() {
    return new XiaomiPhone()
  }
  createTV() {
    return new XiaomiTV()
  }
}
// 使用
let xiaomiFactory = new XiaomiFactory()
let m1 = xiaomiFactory.createPhone();
let m2 = xiaomiFactory.createTV();
console.log(m1, m2) // XiaomiPhone {name: '小米手机'} XiaomiTV {name: '小米电视'}

参考资料


©️版权申明 :版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀

相关推荐
前端大卫30 分钟前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘1 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare1 小时前
浅浅看一下设计模式
前端
Lee川1 小时前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix1 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人1 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl1 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人2 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼2 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端