PHP设计模式 | 策略模式

105 阅读3分钟

1. 引言

在软件开发中,我们经常需要在运行时动态选择不同的算法或行为,而不希望在主代码中充满 if-elseswitch-case 语句。策略模式(Strategy Pattern) 就是为了解决这一问题的一种常用设计模式。

  • 需要支持 多种支付方式(支付宝、微信、银行卡等)。
  • 需要使用 不同的排序算法(快速排序、冒泡排序、归并排序等)。
  • 需要实现 不同的日志存储(文件日志、数据库日志、云日志等)。

如果我们直接在代码中使用 if-else 判断不同情况,会导致代码耦合度高、难以维护、难以扩展策略模式提供了解决方案,让我们可以轻松地动态选择不同的策略,而不会修改主业务逻辑。

2. 核心概念

策略模式的核心思想是 将算法的定义和使用分离,使得算法可以独立于使用它的客户端进行变化。它由以下几个部分组成:

  1. 策略接口(Strategy) :定义所有策略的统一接口。
  2. 具体策略(Concrete Strategy) :实现具体的算法或行为。
  3. 上下文(Context) :维护对策略对象的引用,并在运行时调用策略方法。

3. 应用场景

策略模式适用于以下场景:

  • 多个类只有在算法或行为上有所不同,适合使用策略模式进行封装。
  • 需要在运行时动态选择算法,如不同的支付方式、不同的日志存储方式。
  • 避免冗长的 if-else 或 switch-case 语句,提高代码的可读性和扩展性。

4. 实现步骤

我们以 支付系统 为例,展示如何使用策略模式。

(1)定义策略接口

首先,我们定义一个 PaymentStrategy 接口,所有支付方式都必须实现该接口:

interface PaymentStrategy {
    public function pay($amount);
}

(2)创建具体的支付策略

不同的支付方式(如支付宝、微信、银行卡)实现 PaymentStrategy 接口:

// 支付宝支付
class Alipay implements PaymentStrategy {
    public function pay($amount) {
        echo "使用支付宝支付 $amount 元\n";
    }
}

// 微信支付
class WeChatPay implements PaymentStrategy {
    public function pay($amount) {
        echo "使用微信支付 $amount 元\n";
    }
}

// 银行卡支付
class BankTransfer implements PaymentStrategy {
    public function pay($amount) {
        echo "使用银行卡支付 $amount 元\n";
    }
}

(3)创建上下文类

PaymentContext 负责存储策略对象,并在运行时调用策略:

class PaymentContext {
    private PaymentStrategy $strategy;

    // 设置支付策略
    public function __construct(PaymentStrategy $strategy) {
        $this->strategy = $strategy;
    }

    // 执行支付
    public function executePayment($amount) {
        $this->strategy->pay($amount);
    }
}

(4)客户端调用

现在,客户端可以根据不同的情况,动态选择支付策略:

// 选择支付宝支付
$context = new PaymentContext(new Alipay());
$context->executePayment(200); // 输出:使用支付宝支付 200 元

// 选择微信支付
$context = new PaymentContext(new WeChatPay());
$context->executePayment(500); // 输出:使用微信支付 500 元

// 选择银行卡支付
$context = new PaymentContext(new BankTransfer());
$context->executePayment(1000); // 输出:使用银行卡支付 1000 元

5. 优势和不足

优势

  1. 符合开闭原则(Open/Closed Principle):新增支付方式时,不需要修改现有代码,只需添加新的策略类。
  2. 避免冗长的 if-else 语句:增强了代码的可读性和可维护性。
  3. 高内聚、低耦合:不同策略类相互独立,不会影响其他策略的实现。
  4. 支持运行时动态选择策略,适用于需要灵活切换算法的场景。

不足

  1. 类的数量增加:每种策略都需要一个新的类,可能会导致类过多。
  2. 策略的选择逻辑仍然需要管理:虽然去掉了 if-else 语句,但需要某种方式(如配置、用户输入)来决定使用哪个策略。

6. 总结

策略模式是一种 行为设计模式,它通过封装不同的算法,使其可以互相替换,且不会影响使用算法的代码。