三、工厂模式
通俗解释(理解记忆)
假设我们有一个汽车工厂。我们可以让工厂根据用户的选择生产不同型号的汽车,而用户无需知道具体的汽车制造过程。
工厂模式的优势在于,它隐藏了对象的创建细节,让客户端代码更简洁,同时使得系统更容易扩展。如果有新的汽车型号加入,只需要在工厂中添加相应的生产逻辑,而不需要修改客户端代码。
// 接口或基类
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.
优点
封装对象创建过程: 工厂模式将对象的创建过程封装在工厂类中,使客户端无需关心对象的具体创建细节,提高了代码的封装性。
降低耦合性: 客户端代码与具体产品类解耦,通过工厂类创建对象,减少了对具体类的依赖,降低了系统的耦合性。
易于扩展: 新增产品类只需扩展工厂类,无需修改客户端代码,符合开闭原则,使系统更易于扩展。
统一管理: 工厂模式可以统一管理对象的创建,集中控制,有利于维护和管理