设计模式——策略模式以及基于Spring依赖注入的策略模式的应用

好的,策略模式(Strategy Pattern)是一种行为型设计模式,用于定义一系列算法,并将每个算法封装成独立的类,使得它们可以相互替换 。策略模式的核心思想是将算法与使用算法的客户端解耦,让算法的变化独立于客户端的使用。

1.策略模式的核心概念

  • 策略接口(Strategy Interface)

    定义所有支持的算法的公共接口,所有具体策略类必须实现该接口。

  • 具体策略类(Concrete Strategies)

    实现策略接口的具体算法。

  • 上下文类(Context Class)

    持有一个策略接口的引用,并通过该接口调用具体策略的算法。

2.为什么需要策略模式?

  • 避免冗长的条件判断当代码中存在大量if-elseswitch-case来根据条件选择不同算法时,策略模式可以消除这些重复判断

  • 开闭原则(OCP):新增算法时无需修改现有代码,只需添加新的策略类。

  • 解耦:将算法逻辑与业务逻辑分离,便于维护和扩展。

3.策略模式的实现步骤

**3.**1. 定义策略接口

java 复制代码
// 策略接口:定义算法的抽象
public interface PaymentStrategy {
    void pay(double amount);
}

3.2. 实现具体策略类

java 复制代码
// 具体策略:支付宝支付
public class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用支付宝支付:" + amount + "元");
    }
}

// 具体策略:微信支付
public class WechatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用微信支付:" + amount + "元");
    }
}

3.3 定义上下文类(持有策略的选择)

java 复制代码
// 上下文类:负责调用策略
public class PaymentContext {
    private PaymentStrategy strategy;

    // 设置策略(通过构造器或Setter注入)
    public PaymentContext(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    // 执行支付
    public void executePayment(double amount) {
        strategy.pay(amount);
    }

    // 动态切换策略(可选)
    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
}

3.4. 客户端调用

java 复制代码
public class Client {
    public static void main(String[] args) {
        // 选择支付宝策略
        PaymentContext context = new PaymentContext(new AlipayStrategy());
        context.executePayment(100.0);  // 输出:使用支付宝支付:100.0元

        // 动态切换为微信支付
        context.setStrategy(new WechatPayStrategy());
        context.executePayment(200.0);  // 输出:使用微信支付:200.0元
    }
}

4.策略模式的优点

  1. 灵活切换算法:通过替换策略对象,可以动态改变程序的行为。

  2. 符合开闭原则:新增算法无需修改已有代码。

  3. 消除重复代码:避免多层条件分支的臃肿逻辑。

  4. 高内聚低耦合:每个策略类独立负责自己的算法逻辑。

5.策略模式的典型应用场景

  1. 支付方式选择:支付宝、微信、信用卡等支付方式的切换。

  2. 排序算法选择:根据数据规模选择快速排序、归并排序等。

  3. 折扣策略:满减、打折、积分抵扣等促销活动。

  4. 游戏中的角色行为:不同武器攻击方式、不同移动策略(行走、飞行)。

6. 策略模式与Spring框架的结合

在Spring中,可以通过依赖注入(DI)动态管理策略实现类。例如:

java 复制代码
// 1. 定义策略接口
public interface DiscountStrategy {
    double applyDiscount(double price);
}

// 2. 实现具体策略类
@Component("vipDiscount")  // Spring托管Bean
public class VipDiscountStrategy implements DiscountStrategy {
    @Override
    public double applyDiscount(double price) {
        return price * 0.8;  // VIP打8折
    }
}

@Component("holidayDiscount")
public class HolidayDiscountStrategy implements DiscountStrategy {
    @Override
    public double applyDiscount(double price) {
        return price * 0.9;  // 节假日打9折
    }
}

// 3. 上下文类(使用Spring注入策略)
@Service
public class DiscountContext {
    private final Map<String, DiscountStrategy> strategyMap;

    // 通过构造函数注入所有策略实现类(自动按Bean名称映射)
    public DiscountContext(Map<String, DiscountStrategy> strategyMap) {
        this.strategyMap = strategyMap;
    }

    public double executeDiscount(String strategyName, double price) {
        DiscountStrategy strategy = strategyMap.get(strategyName);
        if (strategy == null) {
            throw new IllegalArgumentException("策略不存在");
        }
        return strategy.applyDiscount(price);
    }
}

// 4. 客户端调用
@RestController
public class OrderController {
    @Autowired
    private DiscountContext discountContext;

    @PostMapping("/checkout")
    public double checkout(@RequestParam String discountType, @RequestParam double price) {
        return discountContext.executeDiscount(discountType, price);
    }
}

在上述的示例中,假期折扣和VIP折扣通过@Component注解均交予Spring容器管理,在DiscountContext中通过不同折扣类型的字符串切换,即可实现不同折扣算法的应用。这个实现相较之于前面的基础策略模式,可以看到在Context中,我们将存储Strategy的属性换成了Map,通过键值对配合Spring框架的依赖注入,实现了在调用者类(Controller)中策略的声明以及If-else的彻底清除(不用Map,那意味着需要在Context或者Controller中编写折扣策略的选择代码),降低代码的耦合度,同时也更为灵活地切换折扣算法。

7.策略模式的缺点

  • 类数量增多:每个算法对应一个类,可能导致类膨胀。

  • 客户端需要了解策略差异:客户端需要知道不同策略的适用场景。

8.总结

策略模式通过将算法封装成独立的类,实现了算法的灵活切换和业务逻辑的解耦。当系统需要在运行时动态选择算法时,策略模式是理想的选择。结合Spring等框架的依赖注入,可以更优雅地管理策略对象,提升代码的可维护性和扩展性。

9.参考

策略模式 | 菜鸟教程

基于SpringBoot的策略模式多实现类注入(Map注入)_springboot 注入map-CSDN博客

......

相关推荐
Hxyle3 小时前
c++设计模式
开发语言·c++·设计模式
摘星编程3 小时前
并发设计模式实战系列(17):信号量(Semaphore)
设计模式·并发编程
琢磨先生David4 小时前
Java 企业级开发设计模式全解析
java·设计模式
不当菜虚困4 小时前
JAVA设计模式——(十一)建造者模式(Builder Pattern)
java·设计模式·建造者模式
codefly-xtl4 小时前
责任链设计模式
java·开发语言·设计模式
冼紫菜5 小时前
如何使用责任链模式优雅实现功能(滴滴司机、家政服务、请假审批等)
java·开发语言·设计模式·责任链模式
ValidationExpression6 小时前
设计模式-策略模式
python·设计模式·策略模式
牛奶咖啡1311 小时前
学习设计模式《八》——原型模式
学习·设计模式·原型模式·浅度克隆·深度克隆·c#的克隆·原型管理器
阑梦清川12 小时前
计算机体系架构-----设计模式:状态模式(从程序员加班问题切入)
设计模式·架构·状态模式
智想天开12 小时前
16.状态模式:思考与解读
设计模式·状态模式