策略模式
本课属于 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 的新类,无需修改现有代码。
挑战
简单让我们使用策略模式构建一个文本格式化系统!你将创建一个系统,可以在运行时切换不同的格式化策略,以各种方式转换文本,非常适合需要支持多种输出格式的应用程序。
你将把代码组织到四个文件中:
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
}
}这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器