Menu
CoddyTech

策略模式

本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 93 课,共 110 课。

策略模式可以让你定义一组算法,将每种算法封装在各自的类中,并在运行时互换。你可以通过接口注入行为,而不是将行为硬编码到类中,这样就能替换策略,而无需修改使用这些策略的类。

设想一个支付系统,你想支持不同的支付方式。与其使用条件语句处理每种支付方式,不如定义一个策略接口,并创建具体实现:

abstract class PaymentStrategy {
  void pay(double amount);
}

class CreditCardPayment implements PaymentStrategy {
  @override
  void pay(double amount) => print('Paid \$$amount with Credit Card');
}

class PayPalPayment implements PaymentStrategy {
  @override
  void pay(double amount) => print('Paid \$$amount with PayPal');
}

class ShoppingCart {
  PaymentStrategy _paymentStrategy;

  ShoppingCart(this._paymentStrategy);

  void setPaymentStrategy(PaymentStrategy strategy) {
    _paymentStrategy = strategy;
  }

  void checkout(double total) {
    _paymentStrategy.pay(total);
  }
}

void main() {
  var cart = ShoppingCart(CreditCardPayment());
  cart.checkout(99.99);  // 已使用信用卡支付 $99.99

  cart.setPaymentStrategy(PayPalPayment());
  cart.checkout(49.99);  // 已使用 PayPal 支付 $49.99
}

ShoppingCart 不知道也不关心支付的工作方式,它只会委托给当前设置的策略。你可以通过创建新的策略类来添加新的支付方式,而无需修改购物车代码。当你有多种方式可以执行某项操作,并且希望动态选择或切换方式时,这种模式非常适合。

challenge icon

挑战

简单

让我们使用策略模式来构建一个文本格式化系统!你将创建一个系统,可以对文本应用不同的格式化策略,让用户无需更改核心文本处理器,就能动态切换格式。

你将把代码整理到两个文件中:

  • formatting_strategies.dart:在这里创建策略系统。定义一个抽象类 FormattingStrategy,其中包含一个方法 String format(String text)。然后实现三个具体策略:
    • UppercaseStrategy:将文本转换为全大写
    • LowercaseStrategy:将文本转换为全小写
    • TitleCaseStrategy:将每个单词的首字母大写(按空格拆分,将每个单词的首字符大写,其余字符小写)
    另外,创建一个持有 FormattingStrategy 的 TextProcessor 类。它应该包含一个接受初始策略的构造函数、一个用于在运行时更改策略的 setStrategy() 方法,以及一个应用当前策略并返回格式化结果的 process(String text) 方法。
  • main.dart:导入你的格式化策略,并演示策略模式如何支持动态切换行为。创建一个初始策略为 UppercaseStrategy 的 TextProcessor。处理文本 hello world 并打印结果。然后切换到 LowercaseStrategy,处理 HELLO WORLD 并打印结果。最后切换到 TitleCaseStrategy,处理 the quick brown fox 并打印结果。

这展示了策略模式的强大之处:你的 TextProcessor 无需了解格式化的具体工作方式。它只需委托给当前设置的策略,因此你可以轻松添加新的格式化选项,而无需修改处理器!

预期输出:

HELLO WORLD
hello world
The Quick Brown Fox

亲手试试

import 'formatting_strategies.dart';

void main() {
  // TODO: 创建一个 TextProcessor,初始使用 UppercaseStrategy
  
  // TODO: 处理文本 'hello world' 并打印结果
  
  // TODO: 切换到 LowercaseStrategy
  
  // TODO: 处理 'HELLO WORLD' 并打印结果
  
  // TODO: 切换到 TitleCaseStrategy
  
  // TODO: 处理 'the quick brown fox' 并打印结果
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Dart 在线编译器