设计模式——策略模式以及基于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博客

......

相关推荐
Seven971 小时前
【设计模式】使用中介者模式实现松耦合设计
java·后端·设计模式
Seven971 小时前
【设计模式】探索状态模式在现代软件开发中的应用
java·后端·设计模式
Seven971 小时前
【设计模式】从事件驱动到即时更新:掌握观察者模式的核心技巧
java·后端·设计模式
Seven972 小时前
【设计模式】责任链模式教你如何优雅地分发任务
java·后端·设计模式
Seven972 小时前
【设计模式】命令模式助力快速添加新命令而不影响现有代码
java·后端·设计模式
这里有鱼汤3 小时前
程序员必看!突破编程瓶颈!这3种设计模式让你的Python项目飞起来
后端·python·设计模式
vker3 小时前
责任链 vs 规则树:如何构建更强大的规则引擎?
后端·设计模式·代码规范
牵牛老人3 小时前
C++设计模式-抽象工厂模式:从原理、适用场景、使用方法,常见问题和解决方案深度解析
c++·设计模式·抽象工厂模式
液态不合群3 小时前
【设计模式】从火车站卖票看代理模式的实际应用
设计模式·代理模式
谢道韫6663 小时前
23种设计模式
设计模式