Menu
CoddyTech

策略模式

本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 69 课,共 87 课。

策略模式是一种行为型设计模式,它可以让你定义一组算法,将每种算法封装在各自的类中,并让它们可以相互替换。你无需硬编码特定行为,而是可以在运行时切换算法,无需更改使用这些算法的代码。

想象一个支持多种支付方式的支付系统。如果不使用策略模式,你最终会写出杂乱的条件逻辑。使用策略模式后,每种支付方式都有自己的策略:

interface PaymentStrategy {
    void pay(int amount);
}

class CreditCardPayment implements PaymentStrategy {
    public void pay(int amount) {
        System.out.println("Paid " + amount + " via Credit Card");
    }
}

class PayPalPayment implements PaymentStrategy {
    public void pay(int amount) {
        System.out.println("Paid " + amount + " via PayPal");
    }
}

上下文类持有对策略的引用,并将工作委托给它。关键在于,上下文不知道自己使用的是哪种具体策略。它只知道接口:

class ShoppingCart {
    private PaymentStrategy paymentStrategy;
    
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }
    
    public void checkout(int amount) {
        paymentStrategy.pay(amount);
    }
}

现在你可以动态更改付款行为:

ShoppingCart cart = new ShoppingCart();

cart.setPaymentStrategy(new CreditCardPayment());
cart.checkout(100);  // 通过信用卡支付了 100

cart.setPaymentStrategy(new PayPalPayment());
cart.checkout(50);   // 通过 PayPal 支付了 50

当你有多种执行某个操作的方式,并且想轻松地在它们之间切换时,策略模式就很有用。添加新的付款方式只需创建一个实现 PaymentStrategy 的新类,无需修改现有代码。

challenge icon

挑战

简单

让我们使用策略模式构建一个文本格式化系统!你将创建一个系统,可以在运行时切换不同的格式化策略,以各种方式转换文本,非常适合需要支持多种输出格式的应用程序。

你将把代码组织到四个文件中:

  • TextFormatter.java:定义 TextFormatter 接口,所有格式化策略都要实现该接口。接口应声明一个方法 String format(String text),它接收一个字符串并返回格式化后的版本。
  • Formatters.java:创建三个实现 TextFormatter 接口的具体策略:

    UpperCaseFormatter:将文本转换为全大写。

    LowerCaseFormatter:将文本转换为全小写。

    TitleCaseFormatter:将每个单词的首字母大写,其余字母小写。单词之间用空格分隔。

  • TextEditor.java:创建使用格式化策略的上下文类。你的 TextEditor 应包含:

    一个用于保存当前 TextFormatter 策略的私有字段。

    一个用于更改当前格式化策略的 setFormatter(TextFormatter formatter) 方法。

    一个 publishText(String text) 方法,用当前格式化器处理文本并打印 Published: [formatted text]。如果尚未设置格式化器,则应原样打印 Published: [original text]。

  • Main.java:将策略系统组合起来!你会收到两个输入:要格式化的文本(String)和格式化样式(String:"upper"、"lower" 或 "title")。

    创建一个 TextEditor,并在设置格式化器之前,先使用输入文本调用 publishText(展示默认行为)。

    然后,根据样式输入设置相应的格式化策略,并再次使用相同的文本调用 publishText,以显示格式化后的结果。

你会依次收到两个输入:要格式化的文本(String)和格式化样式(String)。

例如,输入 hello world 和 title 时,输出如下:

Published: hello world
Published: Hello World

注意,TextEditor 不需要了解具体的格式化逻辑。它只需将任务交给当前设置的策略。这样一来,无需修改编辑器代码,就能轻松添加新的格式化样式!

亲手试试

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String text = scanner.nextLine();
        String style = scanner.nextLine();
        
        // TODO:创建一个 TextEditor 实例
        
        // TODO:用输入的文本调用 publishText(在设置任何格式化器之前)
        
        // TODO:根据输入的样式("upper"、"lower" 或 "title"),
        // 设置相应的格式化器,然后再次调用 publishText
        
    }
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Java 在线编译器