策略模式
适合阅读本专栏的人群包括:
- 想提升代码质量和架构思维的 Java 开发者
- 在工作中面对复杂业务、代码难以维护的工程师
- 想准备面试、系统复习设计模式知识的同学
阅读完本专栏,你将掌握:
- 23 种设计模式的结构、适用场景和最佳实践
- 面向对象六大设计原则的使用方式
- 如何用设计模式解决常见业务场景问题
- 如何重构低质量代码,提升扩展性与可维护性
任何问题都可以在留言区指出,作者看到后会第一时间回复。
概念总是生僻的,可以结合代码多体会多练习。
如果本文章给你带来一点点收获请点点赞支持一下,谢谢各位架构师,技术专家,专业大拿。
其他模式详解:设计模式入门
策略模式 (Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式使得算法可以在不影响客户端的情况下发生变化。策略模式是我认为在开发中最常用的设计模式了。
适用场景
- 多个类只有在算法或行为上稍有不同的情况:使用策略模式可以避免大量的条件(if/else)语句。
- 需要动态地在几种算法之间切换的情况:策略模式可以让对象在运行时选择不同的行为。
策略模式通过将算法封装在独立的策略类中,使得算法可以独立于使用它的客户端变化。这样,可以轻松地在不同的算法之间切换,增加新的算法也非常方便
结构
策略模式包括以下几个部分:
- 策略(Strategy)接口:定义所有支持的算法的公共接口。
- 具体策略(ConcreteStrategy)类:实现了策略接口的具体算法。
- 上下文(Context)类 :使用一个
Strategy对象来配置,并维护对Strategy对象的引用。

优点
- 策略之间独立:每个策略都是独立的类,易于切换和复用。
- 扩展性好:添加新的策略不需要修改现有系统,只需增加新的策略类即可。
- 避免多重条件语句:策略模式通过多态性避免了大量的条件语句。
缺点
- 增加类的数量:每个策略都是一个单独的类,这可能会导致类的数量增加。
- 所有策略类都需要暴露:客户端必须知道所有的策略,并自行决定使用哪一个策略。
代码示例
下面是一个使用策略模式的简单示例,展示了如何使用策略模式来实现不同的支付方式(如信用卡支付、PayPal支付等)
- 策略接口 :
PaymentStrategy定义了一个pay方法,不同的支付方式实现了这个接口。 - 具体策略类 :
CreditCardPayment和PayPalPayment分别实现了不同的支付方式。 - 上下文类 :
ShoppingCart持有一个PaymentStrategy的引用,通过setPaymentStrategy方法来设置具体的支付方式,并通过checkout方法调用当前支付策略的pay方法来进行支付。 - 客户端 :在
StrategyPatternDemo类中,演示了如何通过设置不同的支付策略来实现不同的支付方式。
java
import java.util.ArrayList;
import java.util.List;
// 策略接口
interface PaymentStrategy {
void pay(int amount);
}
// 具体策略类:信用卡支付
class CreditCardPayment implements PaymentStrategy {
private String name;
private String cardNumber;
private String cvv;
private String dateOfExpiry;
public CreditCardPayment(String name, String cardNumber, String cvv, String dateOfExpiry) {
this.name = name;
this.cardNumber = cardNumber;
this.cvv = cvv;
this.dateOfExpiry = dateOfExpiry;
}
@Override
public void pay(int amount) {
System.out.println("Paid " + amount + " using Credit Card.");
}
}
// 具体策略类:PayPal支付
class PayPalPayment implements PaymentStrategy {
private String emailId;
private String password;
public PayPalPayment(String emailId, String password) {
this.emailId = emailId;
this.password = password;
}
@Override
public void pay(int amount) {
System.out.println("Paid " + amount + " using PayPal.");
}
}
// 购物车中的商品类
class Item {
private String code;
private int price;
public Item(String code, int price) {
this.code = code;
this.price = price;
}
public String getCode() {
return code;
}
public int getPrice() {
return price;
}
}
// 上下文类
class ShoppingCart {
private List<Item> items;
private PaymentStrategy paymentStrategy;
public ShoppingCart() {
this.items = new ArrayList<>();
}
public void addItem(Item item) {
items.add(item);
}
public void removeItem(Item item) {
items.remove(item);
}
public int calculateTotal() {
int sum = 0;
for (Item item : items) {
sum += item.getPrice();
}
return sum;
}
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout() {
int total = calculateTotal();
paymentStrategy.pay(total);
}
}
// 客户端
public class StrategyPatternDemo {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
Item item1 = new Item("1234", 10);
Item item2 = new Item("5678", 40);
cart.addItem(item1);
cart.addItem(item2);
// 使用信用卡支付
cart.setPaymentStrategy(new CreditCardPayment("John Doe", "1234567890123456", "786", "12/15"));
cart.checkout();
// 使用PayPal支付
cart.setPaymentStrategy(new PayPalPayment("myemail@example.com", "mypwd"));
cart.checkout();
}
}
由于策略模式在开发中太常用了,我们在举一个基于 Spring 的实现例子
用户在导出数据文件时可选择导出类型,比如 "csv" "json" "xml",系统需要自动选择对应的策略执行。
java
// 策略接口:导出数据
public interface ExportStrategy {
String export();
}
// JSON 导出策略
@Service("jsonExport")
class JsonExportStrategy implements ExportStrategy {
@Override
public String export() {
return "Exporting data in JSON format";
}
}
// CSV 导出策略
@Service("csvExport")
class CsvExportStrategy implements ExportStrategy {
@Override
public String export() {
return "Exporting data in CSV format";
}
}
// XML 导出策略
@Service("xmlExport")
class XmlExportStrategy implements ExportStrategy {
@Override
public String export() {
return "Exporting data in XML format";
}
}
// 策略工厂:自动注入所有策略
@Component
class ExportStrategyFactory {
@Autowired
private Map<String, ExportStrategy> strategyMap;
public ExportStrategy getStrategy(String type) {
return strategyMap.get(type);
}
}
// 业务逻辑层:执行导出
@Service
class ExportService {
@Autowired
private ExportStrategyFactory factory;
public String executeExport(String type) {
ExportStrategy strategy = factory.getStrategy(type);
if (strategy == null) {
throw new IllegalArgumentException("Unsupported export type: " + type);
}
return strategy.export();
}
}
// Controller 示例
@RestController
@RequestMapping("/export")
class ExportController {
@Autowired
private ExportService exportService;
@GetMapping
public String export(@RequestParam String type) {
return exportService.executeExport(type);
}
}
总结
策略模式是一种行为型设计模式,通过定义一组算法(策略)并将它们封装成独立实现类,使它们可以相互替换,从而避免在业务逻辑中出现大量 if-else 或 switch 判断。核心思想是将行为的选择与执行逻辑解耦,让不同策略可根据运行时输入自行切换。策略模式非常适用于存在多种处理方式且可动态扩展的场景,例如不同解析方案、不同导出格式、不同运算逻辑等。它使系统具备更好的扩展性、可维护性,同时遵循开闭原则(OCP):新增策略无需修改原有代码,只需添加新的实现类即可。