三、工厂模式
通俗解释(理解记忆)
假设我们有一个汽车工厂。我们可以让工厂根据用户的选择生产不同型号的汽车,而用户无需知道具体的汽车制造过程。
工厂模式的优势在于,它隐藏了对象的创建细节,让客户端代码更简洁,同时使得系统更容易扩展。如果有新的汽车型号加入,只需要在工厂中添加相应的生产逻辑,而不需要修改客户端代码。
// 接口或基类
class Car {constructor(model) {this.model = model;}displayInfo() {console.log(`This is a ${this.model} car.`);}
}// 具体实现类
class Sedan extends Car {constructor() {super('Sedan');}
}class SUV extends Car {constructor() {super('SUV');}
}// 工厂
class CarFactory {createCar(type) {switch (type) {case 'sedan':return new Sedan();case 'suv':return new SUV();default:throw new Error('Invalid car type');}}
}// 客户端代码
const factory = new CarFactory();const sedanCar = factory.createCar('sedan');
sedanCar.displayInfo(); // 输出: This is a Sedan car.const suvCar = factory.createCar('suv');
suvCar.displayInfo(); // 输出: This is a SUV car.
Car
是一个基类,而 Sedan
和 SUV
是具体的实现类。CarFactory
是工厂类,根据传入的类型创建相应的汽车实例。客户端代码只需要调用工厂的方法,而不需要关心具体的汽车实现类。
对比一下如果不使用工厂模式
// 没有使用工厂模式的代码
class Sedan {constructor() {this.model = 'Sedan';}displayInfo() {console.log(`This is a ${this.model} car.`);}
}class SUV {constructor() {this.model = 'SUV';}displayInfo() {console.log(`This is a ${this.model} car.`);}
}// 客户端代码
const sedanCar = new Sedan();
sedanCar.displayInfo(); // 输出: This is a Sedan car.const suvCar = new SUV();
suvCar.displayInfo(); // 输出: This is a SUV car.
客户端直接实例化了 Sedan
和 SUV
,导致客户端代码与具体的汽车类耦合在一起。如果需要添加新的汽车类型,客户端代码就需要修改,不符合开闭原则。("开闭原则"是面向对象设计中的一个原则,指的是一个软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。简单来说,当需要添加新功能时,应该通过扩展现有代码来实现,而不是直接修改已有的代码。)
现在假设要添加一种新的汽车类型,比如电动车,客户端代码就需要修改
class ElectricCar {constructor() {this.model = 'Electric Car';}displayInfo() {console.log(`This is an ${this.model}.`);}
}// 修改客户端代码
const electricCar = new ElectricCar();
electricCar.displayInfo(); // 输出: This is an Electric Car.
如果使用工厂模式添加新的类型
// 定义汽车接口
class Car {displayInfo() {}
}// 具体的 Sedan 汽车类
class Sedan extends Car {constructor() {super();this.model = 'Sedan';}displayInfo() {console.log(`This is a ${this.model}.`);}
}// 具体的 SUV 汽车类
class SUV extends Car {constructor() {super();this.model = 'SUV';}displayInfo() {console.log(`This is an ${this.model}.`);}
}// 新的 ElectricCar 汽车类
class ElectricCar extends Car {constructor() {super();this.model = 'Electric Car';}displayInfo() {console.log(`This is an ${this.model}.`);}
}// 汽车工厂
class CarFactory {createCar(type) {switch (type) {case 'Sedan':return new Sedan();case 'SUV':return new SUV();case 'ElectricCar':return new ElectricCar();default:throw new Error('Invalid car type.');}}
}// 客户端代码
const carFactory = new CarFactory();// 使用工厂创建 Sedan
const sedan = carFactory.createCar('Sedan');
sedan.displayInfo(); // 输出: This is a Sedan.// 使用工厂创建 SUV
const suv = carFactory.createCar('SUV');
suv.displayInfo(); // 输出: This is an SUV.// 使用工厂创建 ElectricCar
const electricCar = carFactory.createCar('ElectricCar');
electricCar.displayInfo(); // 输出: This is an Electric Car.
优点
-
封装对象创建过程: 工厂模式将对象的创建过程封装在工厂类中,使客户端无需关心对象的具体创建细节,提高了代码的封装性。
-
降低耦合性: 客户端代码与具体产品类解耦,通过工厂类创建对象,减少了对具体类的依赖,降低了系统的耦合性。
-
易于扩展: 新增产品类只需扩展工厂类,无需修改客户端代码,符合开闭原则,使系统更易于扩展。
-
统一管理: 工厂模式可以统一管理对象的创建,集中控制,有利于维护和管理