工厂模式
首发于:2022-03-22
基本概念
工厂模式 (Factory Pattern),根据不同的输入返回不同类的实例,一般用来创建同一类对象。工厂方式的主要思想是将对象的创建与对象的实现分离。
现实生活中的例子
下馆子就是一个典型的工厂模式的例子:
有一天,你朋友来找你玩儿,你带他下馆子去,点菜环节,你跟老板说,来个小炒黄牛肉,再来个麻婆豆腐,再来个 ...... 过了一会儿一大桌子菜就上了桌,你们吃得很 happy。
这个场景中,老板就相当于工厂,你只需要调用老板,告诉他你想要生产什么,他就会负责把产品生产出来,过程中你只需要知道产品名称,而不需要知道生产过程。
应用场景
- 对象的创建比较复杂,而访问者无需知道创建的具体流程;
- 处理大量具有相同属性的小对象。
其实 document.createElement
方法就是一个典型的工厂方法思想,创建元素的内部实现肯定比这要复杂很多,不过我们使用的时候只需要传入标签名(div、img 等)就可以了。
优缺点
优点:
- 良好的封装,代码结构清晰,访问者无需知道对象的创建流程,特别是创建比较复杂的情况下;
- 扩展性优良,通过工厂方法隔离了用户和创建流程隔离,符合开放封闭原则;
- 解耦了高层逻辑和底层产品类,符合最少知识原则,不需要的就不要去交流;
缺点:
- 带来了额外的系统复杂度,增加了抽象性;
实现
简单工厂的实现
使用简单工厂来实现一下上面的饭店:
js
/* 饭店方法 */
class Restaurant {
static order(menu) {
switch (menu) {
case '小炒黄牛肉':
return new XiaoChaoHuangNiuRou()
case '麻婆豆腐':
return new MaPoDouFu()
default:
throw new Error('卖完了')
}
}
}
/* 小炒黄牛肉 */
class XiaoChaoHuangNiuRou {
constructor() {
this.type = '小炒黄牛肉'
}
}
/* 麻婆豆腐 */
class MaPoDouFu {
constructor() {
this.type = '麻婆豆腐'
}
}
Restaurant.order('小炒黄牛肉')
Restaurant.order('红烧排骨')
这种简单工厂适用于产品种类比较少,创建逻辑不复杂的时候使用。
工厂模式实现
上述的方法,不够灵活,扩展性也比较差,如果想要增加菜品就需要,修改工厂类,这是违背开闭原则的,所以只适合比较简单的场景,下面将简单工厂修改为工厂模式(也叫工厂方法模式)
js
/* 饭店方法 */
class Restaurant {
constructor() {
this.menuData = {}
}
/* 点菜 */
order(menu) {
if (!this.menuData[menu]) {
throw new Error('卖完了')
}
const { type } = this.menuData[menu]
return new Menu(type)
}
/* 增加菜品种类 */
addMenu(menu, type) {
if (this.menuData[menu]) {
console.info('已经有这个菜了!')
return
}
this.menuData[menu] = { type }
}
/* 移除菜品 */
removeMenu(menu) {
if (!this.menuData[menu]) return
delete this.menuData[menu]
}
}
/* 菜品类 */
class Menu {
constructor(type) {
this.type = type
}
}
const restaurant = new Restaurant()
restaurant.addMenu('XiaoChaoHuangNiuRou', '小炒黄牛肉') // 注册菜品
restaurant.addMenu('MaPoDouFu', '麻婆豆腐')
restaurant.addMenu('MaPoDouFu', '麻婆豆腐')
restaurant.order('XiaoChaoHuangNiuRou')
restaurant.order('MaPoDouFu')
restaurant.order('DanChaoFan')