JavaScript设计模式「基于ES2024」:创建型模式-工厂模式

123 阅读2分钟

工厂模式提供了一种将对象的创建与使用分离的方法。

class Vehicle {
    constructor(type, wheels) {
        this.type = type;
        this.wheels = wheels;
    }

    getInfo() {
        return `This is a ${this.type} with ${this.wheels} wheels.`;
    }
}

class Car extends Vehicle {
    constructor() {
        super('Car', 4);
    }
}

class Motorcycle extends Vehicle {
    constructor() {
        super('Motorcycle', 2);
    }
}

class Truck extends Vehicle {
    constructor() {
        super('Truck', 6);
    }
}

class VehicleFactory {
    static #vehicleTypes = new Map([
        ['car', Car],
        ['motorcycle', Motorcycle],
        ['truck', Truck]
    ]);

    static #isValidType(type) {
        return VehicleFactory.#vehicleTypes.has(type);
    }

    static createVehicle(type) {
        if (!VehicleFactory.#isValidType(type)) {
            throw new Error(`Invalid vehicle type: ${type}`);
        }
        const VehicleClass = VehicleFactory.#vehicleTypes.get(type);
        return new VehicleClass();
    }

    static addVehicleType(type, vehicleClass) {
        if (typeof type !== 'string' || !(vehicleClass.prototype instanceof Vehicle)) {
            throw new Error('Invalid vehicle type or class');
        }
        VehicleFactory.#vehicleTypes.set(type.toLowerCase(), vehicleClass);
    }
}

// 使用示例
const car = VehicleFactory.createVehicle('car');
console.log(car.getInfo()); // 输出: This is a Car with 4 wheels.

const motorcycle = VehicleFactory.createVehicle('motorcycle');
console.log(motorcycle.getInfo()); // 输出: This is a Motorcycle with 2 wheels.

// 添加新的车辆类型
class Bicycle extends Vehicle {
    constructor() {
        super('Bicycle', 2);
    }
}

VehicleFactory.addVehicleType('bicycle', Bicycle);
const bicycle = VehicleFactory.createVehicle('bicycle');
console.log(bicycle.getInfo()); // 输出: This is a Bicycle with 2 wheels.

// 错误处理示例
try {
    VehicleFactory.createVehicle('boat');
} catch (error) {
    console.error(error.message); // 输出: Invalid vehicle type: boat
}

实现思路

  1. 基类 Vehicle: 定义了所有车辆的通用属性和方法。
  2. 具体车辆类: CarMotorcycleTruck 继承自 Vehicle,实现了特定类型的车辆。
  3. VehicleFactory:
    • 使用静态私有字段 #vehicleTypes 存储可用的车辆类型。
    • 静态私有方法 #isValidType 用于验证车辆类型是否有效。
    • 静态方法 createVehicle 根据给定的类型创建相应的车辆实例。
    • 静态方法 addVehicleType 允许动态添加新的车辆类型。
  4. 错误处理: 对无效的车辆类型抛出错误。
  5. 类型检查: 在 addVehicleType 方法中,确保添加的新类型是 Vehicle 的子类。

优点

  • 封装性: 客户端代码不需要知道具体的车辆类,只需与工厂类交互。
  • 可扩展性: 可以轻松添加新的车辆类型,而不需要修改现有代码。
  • 集中管理: 所有车辆类型的创建逻辑都集中在一个地方,便于维护。
  • 类型安全: 通过类型检查确保只能添加有效的车辆类型。