策略模式:让“选择困难症”变得超简单!

你有没有过这种纠结时刻?点外卖时看满减:「满30减5」「满50减15」「满100减30」,到底选哪个更划算?或者打车时:「快车」「特惠快车」「拼车」,不同车型价格算法不一样……

今天要讲的​​策略模式​​,就是专门解决这种“多选一、动态切换”问题的!用生活里“换着法子算钱”的例子,保证你5分钟懂。

一、生活实例:点外卖凑满减的“算钱游戏”

假设你要点38元的外卖,平台有3种优惠策略:

  • ​策略A​​:满30减5(实付33元)
  • ​策略B​​:满50减15(不够50,用不了)
  • ​策略C​​:无门槛减2(实付36元)

这时候你会选哪个?显然策略A最划算。但如果订单金额变成55元,策略B(减15)会比策略A(减5)更划算。

​问题来了​​:如果每次订单金额变化,都要手动改代码里的“减5”“减15”,是不是很麻烦?比如:

// 烦死!每次金额变了,都要改这里的数字
int finalPrice = 0;
if (amount >= 50) {
    finalPrice = amount - 15;
} else if (amount >= 30) {
    finalPrice = amount - 5;
} else {
    finalPrice = amount - 2;
}

这时候,​​策略模式​​就像个“优惠计算器”——把每种优惠的算法单独封装成“小工具”,需要哪个就调用哪个,灵活得很!

二、Java代码示例:用策略模式实现“自动选最优优惠”

咱们用代码模拟外卖平台的优惠计算,感受策略模式的威力。

步骤1:定义“策略接口”——所有优惠的“统一模板”

不管哪种优惠,核心都是“根据订单金额算最终价格”。所以先定义一个策略接口:

// 优惠策略接口(所有具体优惠的“模板”)
public interface DiscountStrategy {
    // 计算最终价格的方法(参数是订单原价)
    int calculate(int originalPrice);
}

步骤2:实现具体策略——每种优惠的“专属算法”

每种优惠(满减、无门槛)都实现这个接口,把自己的算法写进去。

​策略A:满30减5​

// 满30减5的优惠策略
public class Full30Discount implements DiscountStrategy {
    @Override
    public int calculate(int originalPrice) {
        if (originalPrice >= 30) {
            return originalPrice - 5; // 减5元
        }
        return originalPrice; // 不够30,不能用
    }
}

​策略B:满50减15​

// 满50减15的优惠策略
public class Full50Discount implements DiscountStrategy {
    @Override
    public int calculate(int originalPrice) {
        if (originalPrice >= 50) {
            return originalPrice - 15; // 减15元
        }
        return originalPrice; // 不够50,不能用
    }
}

​策略C:无门槛减2​

// 无门槛减2元的优惠策略(谁都能用)
public class NoThresholdDiscount implements DiscountStrategy {
    @Override
    public int calculate(int originalPrice) {
        return originalPrice - 2; // 直接减2元
    }
}

步骤3:定义“策略上下文”——负责“选策略+计算”

我们需要一个“工具类”,帮我们选择当前适用的策略,并调用它的算法。这个类叫DiscountContext

// 优惠策略上下文(负责选策略、算价格)
public class DiscountContext {
    // 当前使用的策略(默认是无门槛)
    private DiscountStrategy currentStrategy = new NoThresholdDiscount();

    // 动态切换策略(比如根据订单金额自动选最优)
    public void setStrategy(DiscountStrategy strategy) {
        this.currentStrategy = strategy;
    }

    // 计算最终价格(调用当前策略的算法)
    public int computeFinalPrice(int originalPrice) {
        return currentStrategy.calculate(originalPrice);
    }
}

步骤4:客户端调用——像“点菜”一样选策略

现在,客户端(比如你的外卖APP)可以根据订单金额,动态选择最优策略:

public class Client {
    public static void main(String[] args) {
        // 创建策略上下文
        DiscountContext context = new DiscountContext();

        // 场景1:订单38元(选满30减5)
        int order1 = 38;
        context.setStrategy(new Full30Discount()); // 切换到策略A
        int finalPrice1 = context.computeFinalPrice(order1);
        System.out.println("38元订单,满30减5后价格:" + finalPrice1); // 输出33元

        // 场景2:订单55元(选满50减15)
        int order2 = 55;
        context.setStrategy(new Full50Discount()); // 切换到策略B
        int finalPrice2 = context.computeFinalPrice(order2);
        System.out.println("55元订单,满50减15后价格:" + finalPrice2); // 输出40元

        // 场景3:订单15元(只能用无门槛减2)
        int order3 = 15;
        context.setStrategy(new NoThresholdDiscount()); // 切换到策略C
        int finalPrice3 = context.computeFinalPrice(order3);
        System.out.println("15元订单,无门槛减2后价格:" + finalPrice3); // 输出13元
    }
}

​输出结果​​:

38元订单,满30减5后价格:33
55元订单,满50减15后价格:40
15元订单,无门槛减2后价格:13

示意图:策略模式的“工作流程”

客户端 → 选择策略(如满30减5) → 策略上下文调用该策略的算法 → 返回最终价格

三、策略模式的“使用说明书”

1. 适用场景

策略模式最适合这种​​“有多个同类算法,需要动态切换”​​的场景:

  • ​支付方式​​:支付宝、微信、信用卡(每种支付方式的验证逻辑不同)。
  • ​排序算法​​:冒泡排序、快速排序、归并排序(根据数据量大小选不同算法)。
  • ​物流计费​​:普通快递、特快专递、同城闪送(不同配送方式的计费规则)。

2. 优势

  • ​灵活切换​​:想换策略?只需要改一行代码(setStrategy(新策略)),不用改原来的计算逻辑。
  • ​代码干净​​:每种策略的算法独立封装,不会和业务代码“搅成一团”。
  • ​容易扩展​​:新增策略(比如“满100减50”)?只需要写一个新的XXXDiscount类,不用改已有代码。

3. 不足

  • ​策略类变多​​:如果有10种优惠,就要写10个策略类(不过比“if-else地狱”强多了)。
  • ​客户端需了解策略​​:客户端(比如你的APP)需要知道有哪些策略可选(但可以通过“策略工厂”隐藏细节)。

四、常见问题Q&A

​Q1:策略模式和“if-else”有什么区别?​
A:if-else是把所有逻辑写在一个方法里,新增策略要改代码;策略模式是把每个策略单独封装成类,新增策略只需加新类,符合“开闭原则”(对扩展开放,对修改关闭)。比如上面的例子,如果用if-else,加“满100减50”要改computeFinalPrice方法;用策略模式,只需要新建Full100Discount类,客户端调用即可。

​Q2:策略模式需要提前知道所有策略吗?​
A:不需要!策略模式的核心是“运行时动态切换”,客户端可以在需要的时候选择任意策略。比如外卖APP可以在用户下单时,根据金额自动选最优策略(比如“满50减15”比“满30减5”更划算)。

​Q3:策略对象是每次调用都新建吗?​
A:看情况!如果策略无状态(比如“满30减5”的算法不保存任何数据),可以复用同一个实例;如果有状态(比如“用户专属折扣码”),每次调用需要新建实例。

​Q4:策略模式和工厂模式能一起用吗?​
A:当然可以!如果策略很多,可以用“策略工厂”来管理策略的创建(比如根据订单金额返回对应的策略),客户端只需要和工厂打交道,完全隐藏策略细节。

五、使用策略模式的注意事项

  • ​策略接口要稳定​​:策略接口(比如DiscountStrategy)一旦定义,尽量不要修改方法(比如加新参数),否则所有具体策略都要改,会很麻烦。
  • ​策略尽量无状态​​:具体策略类(比如Full30Discount)最好不保存成员变量(比如不记录“当前优惠次数”),否则多个客户端共享同一个实例时可能出问题。
  • ​别滥用策略模式​​:如果只有2-3个简单策略,用if-else可能更简单;但如果策略经常变或需要动态切换,策略模式更合适。

总结

策略模式的核心是“​​把变化的部分(算法)封装起来,不变的部分(调用逻辑)稳定下来​​”。就像你点外卖时,不管选哪种优惠,最后都是“原价-优惠金额”,这个逻辑(调用calculate方法)是不变的;变化的只是“优惠金额怎么算”(不同策略的实现)。

下次遇到“多选一、动态切换”的需求,记得用策略模式,让你的代码像“自动换挡的汽车”一样灵活!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值