什么是JavaScript中的工厂模式?
在JavaScript的设计模式体系中,工厂模式是一种非常基础且常用的创建型模式,它的核心思想是封装对象的创建过程,将对象的实例化逻辑从业务逻辑中抽离出来,让代码更易于维护和扩展。
工厂模式的核心作用
在没有使用工厂模式时,如果我们需要创建多个同类型的对象,往往会在业务代码中重复编写实例化逻辑,比如多次调用构造函数。当对象的创建逻辑变得复杂,或者后续需要修改创建规则时,散落在各处的实例化代码会带来很高的维护成本。工厂模式正是为了解决这个问题:它将对象的创建逻辑集中到一个函数(即工厂函数)中,调用方只需要传入对应的参数,就能获得需要的对象实例,不需要关心对象内部的具体创建细节。
简单工厂模式的实现
简单工厂模式是最基础的工厂模式实现,通过一个工厂函数,根据传入的参数不同,返回不同类型的对象实例。下面我们通过一个创建用户对象的例子来理解它的实现。
// 定义两个不同类型的用户构造函数
function NormalUser(name, age) {
this.name = name;
this.age = age;
this.type = '普通用户';
this.getInfo = function() {
return `姓名:${this.name},年龄:${this.age},类型:${this.type}`;
};
}
function VipUser(name, age, level) {
this.name = name;
this.age = age;
this.level = level;
this.type = 'VIP用户';
this.getInfo = function() {
return `姓名:${this.name},年龄:${this.age},类型:${this.type},VIP等级:${this.level}`;
};
}
// 工厂函数,根据传入的type参数返回对应的用户实例
function userFactory(type, options) {
switch(type) {
case 'normal':
return new NormalUser(options.name, options.age);
case 'vip':
return new VipUser(options.name, options.age, options.level);
default:
throw new Error('不支持的用户类型');
}
}
// 使用工厂创建对象
try {
const user1 = userFactory('normal', { name: '张三', age: 20 });
console.log(user1.getInfo()); // 输出:姓名:张三,年龄:20,类型:普通用户
const user2 = userFactory('vip', { name: '李四', age: 25, level: 3 });
console.log(user2.getInfo()); // 输出:姓名:李四,年龄:25,类型:VIP用户,VIP等级:3
} catch (e) {
console.error(e.message);
}上面的代码中,userFactory 就是工厂函数,它接收用户类型和配置参数,内部根据类型判断需要实例化哪个构造函数,最终返回对应的用户对象。调用方不需要知道 NormalUser 和 VipUser 的具体实现,只需要和工厂函数交互即可。
工厂模式的优缺点
优点
- 解耦创建逻辑和业务逻辑:对象的创建过程被封装在工厂函数中,业务代码只需要关心如何使用对象,不需要关心对象怎么创建。
- 降低维护成本:如果后续需要新增用户类型,或者修改现有用户的创建逻辑,只需要在工厂函数中修改,不需要改动所有调用创建逻辑的地方。
- 符合单一职责原则:工厂函数只负责创建对象,业务代码只负责处理业务逻辑,职责划分更清晰。
缺点
- 简单工厂模式不符合开闭原则:如果需要新增对象类型,需要修改工厂函数内部的判断逻辑,而不是通过扩展的方式实现。
- 当工厂函数需要创建的对象类型过多时,工厂函数会变得臃肿,维护难度上升。
工厂模式的适用场景
工厂模式适合以下场景使用:
- 需要创建的对象类型较多,且创建逻辑存在一定复杂度,不想在业务代码中重复编写创建逻辑。
- 希望隐藏对象的创建细节,调用方只需要通过简单的参数就能获取对象实例。
- 后续可能会频繁新增或修改对象的创建规则,需要降低代码的维护成本。
需要注意的是,如果只需要创建少量简单的对象,直接使用构造函数实例化反而更直观,不需要过度使用工厂模式,避免代码变得冗余。