JavaScript设计模式「基于ES2024」:行为型模式-策略模式

55 阅读2分钟

策略模式定义了算法家族,分别封装起来,让它们之间可以互相替换。这种模式让算法的变化独立于使用算法的客户端。

// 策略接口
class PaymentStrategy {
    pay(amount) {
        throw new Error('Method not implemented');
    }
}

// 具体策略:信用卡支付
class CreditCardPayment extends PaymentStrategy {
    #cardNumber;
    #name;

    constructor(cardNumber, name) {
        super();
        this.#cardNumber = cardNumber;
        this.#name = name;
    }

    pay(amount) {
        console.log(`Paid $${amount} using Credit Card (${this.#cardNumber})`);
    }
}

// 具体策略:PayPal支付
class PayPalPayment extends PaymentStrategy {
    #email;

    constructor(email) {
        super();
        this.#email = email;
    }

    pay(amount) {
        console.log(`Paid $${amount} using PayPal (${this.#email})`);
    }
}

// 具体策略:Apple Pay支付
class ApplePayPayment extends PaymentStrategy {
    #deviceId;

    constructor(deviceId) {
        super();
        this.#deviceId = deviceId;
    }

    pay(amount) {
        console.log(`Paid $${amount} using Apple Pay (Device: ${this.#deviceId})`);
    }
}

// 上下文类:支付处理器
class PaymentProcessor {
    #strategy;

    constructor(strategy) {
        this.#strategy = strategy;
    }

    setStrategy(strategy) {
        this.#strategy = strategy;
    }

    processPayment(amount) {
        this.#strategy.pay(amount);
    }
}

// 支付系统类
class PaymentSystem {
    #strategies = new Map();
    #processor;

    constructor() {
        this.#processor = new PaymentProcessor(null);
    }

    addPaymentStrategy(name, strategy) {
        this.#strategies.set(name, strategy);
    }

    pay(strategyName, amount) {
        const strategy = this.#strategies.get(strategyName);
        if (strategy) {
            this.#processor.setStrategy(strategy);
            this.#processor.processPayment(amount);
        } else {
            console.log(`Payment method ${strategyName} not supported`);
        }
    }
}

// 使用示例
function demonstrateStrategy() {
    const paymentSystem = new PaymentSystem();

    paymentSystem.addPaymentStrategy('credit_card', new CreditCardPayment('1234-5678-9012-3456', 'John Doe'));
    paymentSystem.addPaymentStrategy('paypal', new PayPalPayment('john.doe@example.com'));
    paymentSystem.addPaymentStrategy('apple_pay', new ApplePayPayment('iPhone12-ABCD'));

    console.log("Processing payments using different strategies:");
    paymentSystem.pay('credit_card', 100);
    paymentSystem.pay('paypal', 50);
    paymentSystem.pay('apple_pay', 75);
    paymentSystem.pay('bitcoin', 200);  // 不支持的支付方式
}

demonstrateStrategy();

实现思路

  1. PaymentStrategy 接口:定义了所有具体支付策略必须实现的 pay 方法。

  2. 具体策略类(CreditCardPayment, PayPalPayment, ApplePayPayment

    • 每个类代表一种特定的支付方式。
    • 每个类都实现了 PaymentStrategy 接口中定义的 pay 方法。
    • 使用私有字段来存储支付方式特定的信息。
  3. PaymentProcessor 类(上下文)

    • 持有一个当前的支付策略。
    • 提供了设置策略和处理支付的方法。
    • 在处理支付时,委托给当前的支付策略。
  4. PaymentSystem

    • 管理多个支付策略。
    • 使用 Map 来存储不同的支付策略。
    • 提供了添加新策略和使用特定策略进行支付的方法。

优点

  • 算法的分离:不同的支付算法被封装在各自的类中,易于维护和扩展。
  • 策略的动态切换:可以在运行时根据需要切换不同的支付策略。
  • 开闭原则:可以轻松添加新的支付策略而不修改现有代码。
  • 消除了条件语句:避免了使用复杂的条件语句来选择支付方式。