工厂模式
简单工厂模式
先看一个例子:
class Car {}
class Benz extends Car {}
class BMW extends Car {}
class Audi extends Car {}
const benz = new Benz();
const bmw = new BMW();
const audi = new Audi();
使用简单工厂模式改造后的例子:
class Car {}
class Benz extends Car {}
class BMW extends Car {}
class Audi extends Car {}
class CarFactory {
static createCar(type) {
switch (type) {
case 'benz':
return new Benz();
case 'bmw':
return new BMW();
case 'audi':
return new Audi();
default:
throw new Error('type error');
}
}
}
const benz = CarFactory.createCar('benz');
const bmw = CarFactory.createCar('bmw');
const audi = CarFactory.createCar('audi');
可以看到,简单工厂模式是定义一个类来创建其他类的实例,根据参数的不同返回不同类的实例,通常这些类拥有相同的父类。
好处是:
- 将创建逻辑都集中在工厂类中,便于集中管理,而不是分散暴露在代码里
- 提高代码可读性和可维护性
使用函数形式的例子:
function Car() {}
function Benz() {}
Benz.prototype = Object.create(Car.prototype);
function BMW() {}
BMW.prototype = Object.create(Car.prototype);
function Audi() {}
Audi.prototype = Object.create(Car.prototype);
// 工厂函数
function createCar(type) {
switch (type) {
case 'benz':
return new Benz();
case 'bmw':
return new BMW();
case 'audi':
return new Audi();
default:
throw new Error('type error');
}
}
const benz = createCar('benz');
const bmw = createCar('bmw');
const audi = createCar('audi');
工厂模式和构造器模式的区别
构造器解决的是多个对象实例的问题,工厂模式解决的是多个类的问题。
工厂方法模式
工厂方法模式是简单工厂的进一步优化,不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。
工厂方法模式将创建对象的职责下放到子类,通过子类来决定创建哪种具体类型的对象。
class Car {}
class Benz extends Car {}
class BMW extends Car {}
class Audi extends Car {}
// 定义一个创建对象的接口
class CarFactory {
createCar() {
throw new Error('不允许直接调用,这个方法应该被覆盖');
}
}
class BenzFactory extends CarFactory {
createCar() {
return new Benz();
}
}
class BMWFactory extends CarFactory {
createCar() {
return new BMW();
}
}
class AudiFactory extends CarFactory {
createCar() {
return new Audi();
}
}
const benzFactory = new BenzFactory();
const benz = benzFactory.createCar();
const bmwFactory = new BMWFactory();
const bmw = bmwFactory.createCar();
const audiFactory = new AudiFactory();
const audi = audiFactory.createCar();
工厂方法模式的步骤:
- 定义产品父类:Car
- 定义子类实现父类,并重写父类方法:Benz、Audi、BMW
- 定义抽象接口,以及抽象方法:CarFactory
- 定义工厂类,继承抽象接口,实现抽象方法:BenzFactory、BMWFactory、AudiFactory
- new 工厂类,调用方法进行实例化
如果要新增一个产品,相比简单工厂模式的优势:
- 简单工厂模式,需要修改工厂类,违背了「开闭原则」
- 工厂方法模式,只需要增加产品类和工厂类,不需要修改抽象接口
抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
抽象工厂模式包含如下 4 种角色:
- 抽象工厂
- 具体工厂
- 抽象产品
- 具体产品
示例:汽车厂商能生产轮胎、发动机
- 先定义一个汽车厂商的抽象工厂 AutomakerFactory,提供 2 个抽象方法 createWheel 和 createEngine
class AutomakerFactory {
createWheel() {
throw new Error('不能调用抽象方法');
}
createEngine() {
throw new Error('不能调用抽象方法');
}
}
- 定义一个具体工厂,实现抽象工厂的抽象方法,生产轮胎和发动机
class BenzFactory extends AutomakerFactory {
createWheel() {
return new BenzWheel();
}
createEngine() {
return new BenzEngine();
}
}
class AudiFactory extends AutomakerFactory {
createWheel() {
return new AudiWheel();
}
createEngine() {
return new AudiEngine();
}
}
- 定义抽象产品类 Wheel 和 具体产品类 BenzWheel、AudiWheel:
class Wheel {
turn() {
throw new Error('不能调用抽象方法');
}
}
class BenzWheel extends Wheel {
turn() {
console.log('Benz turn');
}
}
class AudiWheel extends Wheel {
turn() {
console.log('Audi turn');
}
}
- 定义抽象产品类 Engine 和 具体产品类 BenzEngine、AudiEngine:
class Engine {
start() {
throw new Error('不能调用抽象方法');
}
}
class BenzEngine extends Engine {
start() {
console.log('Benz engine start');
}
}
class AudiEngine extends Engine {
start() {
console.log('Audi engine start');
}
}
- 实例化过程
let benz = new BenzFactory();
let benzWheel = benz.createWheel();
let benzEngine = benz.createEngine();
let audi = new AudiFactory();
let audiWheel = audi.createWheel();
let audiEngine = audi.createEngine();
benzWheel.turn(); // Benz turn
benzEngine.start(); // Benz engine start
audiWheel.turn(); // Audi turn
audiEngine.start(); // Audi engine start