设计模式之策略模式

一、定义

策略模式定义了一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。本模式使得算法可独立于使用它的客户端而变化。

通俗理解:将一组相似的行为抽象出来,通过统一的接口进行约束,客户端根据实际情况选择使用哪种行为策略。

二、适用场景

策略模式适用于以下场景:

  • 系统中有许多类仅在行为上略有不同,使用条件语句(if-elseswitch-case)判断行为;
  • 希望将算法的使用与实现解耦,使代码更加灵活可扩展;
  • 需要动态地在运行时切换不同的算法或行为;
  • 需要避免类中膨胀的行为逻辑,使得行为扩展对调用者透明。

三、核心角色

策略模式包含以下几个核心角色:

角色

说明

Context

上下文类,持有一个策略对象,并调用策略对象的方法来完成任务

Strategy(接口)

抽象策略,定义所有支持的算法的公共接口

ConcreteStrategy

具体策略,实现具体的算法或行为


四、UML 类图结构


     +----------------+         
     |   Strategy     |<-------------------+
     | +execute()     |                    |
     +----------------+                    |
              ▲                            |
              |                            |
+------------------------+     +------------------------+
|   ConcreteStrategyA    |     |   ConcreteStrategyB    |
| +execute()             |     | +execute()             |
+------------------------+     +------------------------+
              ▲                            
              |
      +---------------+
      |   Context      |
      | - strategy     |
      | +setStrategy() |
      | +doSomething() |
      +---------------+

五、真实业务场景示例

需求背景:

假设我们有一个在线商城,支持多种促销策略:满减、打折、返现、无优惠等。每种促销策略的计算逻辑不同,我们希望用户下单时能自动选择合适的策略,并方便后续扩展。

1. 抽象策略接口(Strategy 角色)

// 抽象策略角色:定义所有具体策略的统一接口
public interface PromotionStrategy {
    void execute();
}

2. 具体策略类(ConcreteStrategy 角色)

// 具体策略类A:满减策略
public class FullReductionStrategy implements PromotionStrategy {
    @Override
    public void execute() {
        System.out.println("执行满减策略:满200减50");
    }
}

// 具体策略类B:打折策略
public class DiscountStrategy implements PromotionStrategy {
    @Override
    public void execute() {
        System.out.println("执行打折策略:打8折");
    }
}

// 具体策略类C:返现策略
public class CashbackStrategy implements PromotionStrategy {
    @Override
    public void execute() {
        System.out.println("执行返现策略:返现30元");
    }
}

// 具体策略类D:无促销策略
public class NoPromotionStrategy implements PromotionStrategy {
    @Override
    public void execute() {
        System.out.println("无促销活动");
    }
}

3. 上下文类(Context 角色)

// 上下文角色:用于持有某个策略对象并调用其方法
public class PromotionContext {
    private PromotionStrategy strategy;

    public PromotionContext(PromotionStrategy strategy) {
        this.strategy = strategy;
    }

    // 可选:运行时切换策略
    public void setStrategy(PromotionStrategy strategy) {
        this.strategy = strategy;
    }

    // 执行当前策略
    public void executeStrategy() {
        if (strategy != null) {
            strategy.execute();
        } else {
            System.out.println("未设置促销策略");
        }
    }
}

4. 客户端代码

// 客户端角色:负责选择合适的策略并传给上下文
public class PromotionTest {
    public static void main(String[] args) {
        PromotionContext context;

        // 使用满减策略
        context = new PromotionContext(new FullReductionStrategy());
        context.executeStrategy();

        // 使用打折策略
        context.setStrategy(new DiscountStrategy());
        context.executeStrategy();

        // 使用返现策略
        context.setStrategy(new CashbackStrategy());
        context.executeStrategy();

        // 使用无优惠策略
        context.setStrategy(new NoPromotionStrategy());
        context.executeStrategy();
    }
}

六、优缺点分析

✅ 优点

  1. 扩展性强:新增策略只需实现接口,符合开闭原则;
  2. 消除冗长判断:避免if-elseswitch带来的代码臃肿;
  3. 复用性高:策略类之间相互独立,可复用于不同业务场景;
  4. 更灵活可维护:行为和上下文解耦,修改行为不影响上下文代码。

❌ 缺点

  1. 策略类数量增多:每新增一种行为都要创建一个类,可能造成类爆炸;
  2. 客户端需要了解策略:使用者需要知道有哪些策略才能选择,策略选择逻辑如果不统一,也可能分散;
  3. 策略切换逻辑可能复杂:若需在运行时动态决定策略,需要额外的工厂或注册机制(如策略工厂+枚举)。

七、策略模式与其他模式对比

模式

相似点

区别

状态模式

都是封装行为类,通过上下文调用不同的行为

状态模式强调对象状态转换,而策略模式更强调行为选择

简单工厂模式

可用于策略选择

策略模式注重行为抽象与可替换,工厂只是选择实现的一种方式

策略 + 工厂

工厂封装策略创建逻辑,避免业务方知道具体策略类名

是策略模式的一种组合用法

八、总结

策略模式是行为型设计模式中非常常用的一种,它通过将行为算法独立封装,提升了系统的扩展性和灵活性,尤其适用于行为变动频繁的业务场景。尽管它带来了类的数量增加,但其带来的结构清晰和维护便利往往更值得。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码蚁Q

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值