23种设计模式-19策略模式(Strategy Pattern)

策略模式

适合阅读本专栏的人群包括:

  • 想提升代码质量和架构思维的 Java 开发者
  • 在工作中面对复杂业务、代码难以维护的工程师
  • 想准备面试、系统复习设计模式知识的同学

阅读完本专栏,你将掌握:

  • 23 种设计模式的结构、适用场景和最佳实践
  • 面向对象六大设计原则的使用方式
  • 如何用设计模式解决常见业务场景问题
  • 如何重构低质量代码,提升扩展性与可维护性

任何问题都可以在留言区指出,作者看到后会第一时间回复。

概念总是生僻的,可以结合代码多体会多练习。

如果本文章给你带来一点点收获请点点赞支持一下,谢谢各位架构师,技术专家,专业大拿。

其他模式详解:设计模式入门

策略模式 (Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式使得算法可以在不影响客户端的情况下发生变化。策略模式是我认为在开发中最常用的设计模式了。

适用场景

  • 多个类只有在算法或行为上稍有不同的情况:使用策略模式可以避免大量的条件(if/else)语句。
  • 需要动态地在几种算法之间切换的情况:策略模式可以让对象在运行时选择不同的行为。

策略模式通过将算法封装在独立的策略类中,使得算法可以独立于使用它的客户端变化。这样,可以轻松地在不同的算法之间切换,增加新的算法也非常方便

结构

策略模式包括以下几个部分:

  1. 策略(Strategy)接口:定义所有支持的算法的公共接口。
  2. 具体策略(ConcreteStrategy)类:实现了策略接口的具体算法。
  3. 上下文(Context)类 :使用一个 Strategy 对象来配置,并维护对 Strategy 对象的引用。

优点

  • 策略之间独立:每个策略都是独立的类,易于切换和复用。
  • 扩展性好:添加新的策略不需要修改现有系统,只需增加新的策略类即可。
  • 避免多重条件语句:策略模式通过多态性避免了大量的条件语句。

缺点

  • 增加类的数量:每个策略都是一个单独的类,这可能会导致类的数量增加。
  • 所有策略类都需要暴露:客户端必须知道所有的策略,并自行决定使用哪一个策略。

代码示例

下面是一个使用策略模式的简单示例,展示了如何使用策略模式来实现不同的支付方式(如信用卡支付、PayPal支付等)

  1. 策略接口PaymentStrategy 定义了一个 pay 方法,不同的支付方式实现了这个接口。
  2. 具体策略类CreditCardPaymentPayPalPayment 分别实现了不同的支付方式。
  3. 上下文类ShoppingCart 持有一个 PaymentStrategy 的引用,通过 setPaymentStrategy 方法来设置具体的支付方式,并通过 checkout 方法调用当前支付策略的 pay 方法来进行支付。
  4. 客户端 :在 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):新增策略无需修改原有代码,只需添加新的实现类即可。

相关推荐
qq_2153978971 小时前
java 依赖包引入本地maven库
java·maven
青衫码上行1 小时前
【JavaWeb学习 | 第18篇】Servlet与MVC
java·学习·servlet·mvc
IDOlaoluo1 小时前
apache-maven-3.9.9-bin.zip 使用步骤(超简单版)
java·maven·apache
曹牧1 小时前
Java:list<map<string,sting>>与C#互操作
java·c#·list
卷到起飞的数分1 小时前
23.Maven高级——私服
java·maven
ゞ 正在缓冲99%…1 小时前
2025.9.24华为软开
java·算法·华为
Zzzzzxl_1 小时前
互联网大厂Java/Agent面试实战:JVM、Spring Boot、微服务与RAG全栈问答
java·jvm·springboot·agent·rag·microservices·vectordb
cmdch20171 小时前
AWS亚马逊
java
Qiuner1 小时前
Spring Boot 机制四: AOP 代理机制源码级深度解析(JDK / CGLIB 全链路)
java·spring boot·后端