JavaScript中实现工厂模式详解
工厂模式是软件开发中常用的创建型设计模式,它的核心思想是将对象的创建逻辑封装在一个函数或类中,调用者不需要关心对象的具体创建细节,只需要传入对应的参数就能得到需要的对象实例。这种模式能降低代码耦合度,让对象创建逻辑更加灵活可维护。在JavaScript中,由于语言本身的灵活性,实现工厂模式有多种方式,下面我们逐一介绍。
简单工厂模式
简单工厂模式是最基础的工厂模式实现,它的核心是一个工厂函数,函数内部根据传入的参数判断需要创建的对象类型,然后返回对应的实例。这种方式适合创建的对象类型不多、逻辑相对简单的场景。
下面我们以创建不同类型的用户对象为例,实现一个简单工厂:
// 定义不同类型的用户类
class OrdinaryUser {
constructor(name) {
this.name = name;
this.type = 'ordinary';
}
getInfo() {
return `普通用户:${this.name},类型:${this.type}`;
}
}
class VipUser {
constructor(name) {
this.name = name;
this.type = 'vip';
this.discount = 0.8;
}
getInfo() {
return `VIP用户:${this.name},类型:${this.type},折扣:${this.discount}`;
}
}
class AdminUser {
constructor(name) {
this.name = name;
this.type = 'admin';
this.permissions = ['查询', '修改', '删除'];
}
getInfo() {
return `管理员:${this.name},类型:${this.type},权限:${this.permissions.join('、')}`;
}
}
// 简单工厂函数
function userFactory(type, name) {
switch (type) {
case 'ordinary':
return new OrdinaryUser(name);
case 'vip':
return new VipUser(name);
case 'admin':
return new AdminUser(name);
default:
throw new Error('不支持的用户类型');
}
}
// 使用示例
try {
const user1 = userFactory('ordinary', '张三');
console.log(user1.getInfo()); // 输出:普通用户:张三,类型:ordinary
const user2 = userFactory('vip', '李四');
console.log(user2.getInfo()); // 输出:VIP用户:李四,类型:vip,折扣:0.8
const user3 = userFactory('admin', '王五');
console.log(user3.getInfo()); // 输出:管理员:王五,类型:admin,权限:查询、修改、删除
// 传入不支持的类型会抛出错误
const user4 = userFactory('other', '赵六');
} catch (e) {
console.error(e.message); // 输出:不支持的用户类型
}上面的实现中,我们首先定义了三个不同的用户类,然后编写了userFactory工厂函数,函数根据传入的type参数判断创建哪种类型的用户实例。调用者只需要知道传入对应的类型和名称,不需要关心每个用户类的具体构造逻辑,后续如果需要新增用户类型,只需要在工厂函数的switch分支中新增对应逻辑即可。
工厂方法模式
简单工厂模式有一个明显的缺点:如果需要新增对象类型,必须修改工厂函数的内部逻辑,违反了开闭原则(对扩展开放,对修改关闭)。工厂方法模式可以解决这个问题,它的核心是将对象的创建逻辑延迟到子类中,每个对象类型对应一个具体的工厂子类,新增类型时只需要新增对应的工厂子类,不需要修改原有代码。
以下是工厂方法模式的实现示例:
// 抽象用户类
class User {
constructor(name) {
this.name = name;
}
getInfo() {
throw new Error('子类必须实现getInfo方法');
}
}
// 具体用户类
class OrdinaryUser extends User {
constructor(name) {
super(name);
this.type = 'ordinary';
}
getInfo() {
return `普通用户:${this.name},类型:${this.type}`;
}
}
class VipUser extends User {
constructor(name) {
super(name);
this.type = 'vip';
this.discount = 0.8;
}
getInfo() {
return `VIP用户:${this.name},类型:${this.type},折扣:${this.discount}`;
}
}
// 抽象工厂类
class UserFactory {
createUser(name) {
throw new Error('子类必须实现createUser方法');
}
}
// 具体工厂类
class OrdinaryUserFactory extends UserFactory {
createUser(name) {
return new OrdinaryUser(name);
}
}
class VipUserFactory extends UserFactory {
createUser(name) {
return new VipUser(name);
}
}
// 使用示例
const ordinaryFactory = new OrdinaryUserFactory();
const ordinaryUser = ordinaryFactory.createUser('张三');
console.log(ordinaryUser.getInfo()); // 输出:普通用户:张三,类型:ordinary
const vipFactory = new VipUserFactory();
const vipUser = vipFactory.createUser('李四');
console.log(vipUser.getInfo()); // 输出:VIP用户:李四,类型:vip,折扣:0.8
// 新增Admin用户时,只需要新增AdminUser类和AdminUserFactory类,不需要修改原有工厂代码
class AdminUser extends User {
constructor(name) {
super(name);
this.type = 'admin';
this.permissions = ['查询', '修改', '删除'];
}
getInfo() {
return `管理员:${this.name},类型:${this.type},权限:${this.permissions.join('、')}`;
}
}
class AdminUserFactory extends UserFactory {
createUser(name) {
return new AdminUser(name);
}
}
const adminFactory = new AdminUserFactory();
const adminUser = adminFactory.createUser('王五');
console.log(adminUser.getInfo()); // 输出:管理员:王五,类型:admin,权限:查询、修改、删除工厂方法模式中,我们首先定义了抽象的User类和UserFactory类,规定了子类必须实现的方法。然后每个具体的用户类对应一个具体的工厂子类,负责创建对应的用户实例。如果后续需要新增AdminUser类型,只需要新增AdminUser类和AdminUserFactory类,原有的其他工厂和类都不需要修改,符合开闭原则,更适合复杂场景下扩展。
抽象工厂模式
抽象工厂模式是工厂模式中最高级的实现,它用于创建一系列相关或相互依赖的对象族,而不需要指定它们具体的类。比如我们可能需要创建不同品牌下的手机和对应的充电器,这两个产品属于同一个品牌族,就可以用抽象工厂模式来实现。
以下是抽象工厂模式的实现示例:
// 抽象产品类:手机
class Phone {
constructor(brand) {
this.brand = brand;
}
call() {
throw new Error('子类必须实现call方法');
}
}
// 抽象产品类:充电器
class Charger {
constructor(brand) {
this.brand = brand;
}
charge() {
throw new Error('子类必须实现charge方法');
}
}
// 具体产品类:苹果手机、苹果充电器
class IPhone extends Phone {
call() {
return `${this.brand}手机可以打电话`;
}
}
class ICharger extends Charger {
charge() {
return `${this.brand}充电器可以给苹果设备充电`;
}
}
// 具体产品类:华为手机、华为充电器
class HWPhone extends Phone {
call() {
return `${this.brand}手机支持5G通话`;
}
}
class HWCharger extends Charger {
charge() {
return `${this.brand}充电器支持超级快充`;
}
}
// 抽象工厂类
class DeviceFactory {
createPhone() {
throw new Error('子类必须实现createPhone方法');
}
createCharger() {
throw new Error('子类必须实现createCharger方法');
}
}
// 具体工厂类:苹果设备工厂
class IDeviceFactory extends DeviceFactory {
createPhone() {
return new IPhone('苹果');
}
createCharger() {
return new ICharger('苹果');
}
}
// 具体工厂类:华为设备工厂
class HWDeviceFactory extends DeviceFactory {
createPhone() {
return new HWPhone('华为');
}
createCharger() {
return new HWCharger('华为');
}
}
// 使用示例
function useDevice(factory) {
const phone = factory.createPhone();
const charger = factory.createCharger();
console.log(phone.call());
console.log(charger.charge());
}
// 使用苹果设备
const iFactory = new IDeviceFactory();
useDevice(iFactory);
// 输出:
// 苹果手机可以打电话
// 苹果充电器可以给苹果设备充电
// 使用华为设备
const hwFactory = new HWDeviceFactory();
useDevice(hwFactory);
// 输出:
// 华为手机支持5G通话
// 华为充电器支持超级快充抽象工厂模式适合需要创建多个产品族的场景,每个具体工厂负责创建属于同一个族的所有产品。如果后续需要新增一个新的品牌,比如小米,只需要新增MiPhone、MiCharger类和MIDeviceFactory工厂类即可,不需要修改原有代码,扩展性非常好。
三种工厂模式的适用场景
- 简单工厂模式:适合创建的对象类型少、创建逻辑简单的场景,实现成本低,但是不符合开闭原则,扩展时需要修改工厂函数。
- 工厂方法模式:适合单个产品的创建场景,需要频繁扩展产品类型的情况,符合开闭原则,但是会增加类的数量。
- 抽象工厂模式:适合需要创建多个相关产品族的场景,比如不同品牌下的整套产品,扩展产品族方便,但是扩展新的产品类型(比如新增平板产品)会比较麻烦,需要修改所有工厂类。
在实际开发中,可以根据具体的业务场景选择合适的工厂模式实现,JavaScript的灵活性也让这些模式的实现更加简洁,不需要像强类型语言那样严格定义抽象类和接口,也可以实现类似的效果。
JavaScript工厂模式简单工厂工厂方法模式抽象工厂模式设计模式 本作品最后修改时间:2026-05-23 23:25:46