策略模式
一、什么是策略模式(What)?
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
翻译成人话:对变化的参数 运行 对应的程序。会联想到:if(...){..}else if(...){}... ,但if-else用的多了,程序可读性和维护程度就大大下降。
二、为什么要用策略模式(Why)?
就是为了解决多层if-else判断嵌套的头疼问题,一个问题对应一个策略。
三、怎么使用策略模式(How)?
这里直接用一个 大家熟悉的 “淘宝活动折扣”为例。不同活动期间,对总价(money)进行不同的折扣计算最终应付款(dues)。代码如下:
1. 应付款 抽象类
/** * @Description: * @Author: HanSir * @CreateDate: 2022/3/20 13:45 **/ abstract class ActivityAbstract { /** * 活动期应付款 * * @param money 原价 * @return 折扣后应付款 */ public abstract double dues(double money); }
2. 多个不同活动 应付款子类
(1)正常时期 应付款类
public class ActivityNormal extends ActivityAbstract { /** * 活动期应付款 * * @param money 原价 * @return 折扣后应付款 */ @Override public double dues(double money) { // 原价 return money; } }
(2)618年中大促 应付款类
public class Activity0618 extends ActivityAbstract { /** * 活动期应付款 * * @param money 原价 * @return 折扣后应付款 */ @Override public double dues(double money) { // 满500元 减1元 if(money >= 500) { money = money-1; } return money; } }
(3)双11活动 应付款类
public class Activity1111 extends ActivityAbstract { /** * 活动期应付款 * * @param money 原价 * @return 折扣后应付款 */ @Override public double dues(double money) { // 全场半价 return money / 2; } }
3. 活动上下文分析类
public class ActivityContext { private ActivityAbstract activity = null; /** * 根据活动类型 构造 对应的 活动类 * * @param type 活动类型 */ public ActivityContext(String type) { switch (type) { case "0618": activity = new Activity0618(); break; case "1111": activity = new Activity1111(); break; default: activity = new ActivityNormal(); } } /** * 从对应的活动,获取 应付款 * * @param money 原价 * @return 应付款 */ public double getDues(Double money) { return activity.dues(money); } }
4. 运行调用
public class RunTest { public static void main(String[] args) { double money = 600; // 正常价 ActivityContext context1 = new ActivityContext("正常"); double moneyNormal = context1.getDues(money); System.out.println("正常时期,应付款:" + moneyNormal); // 618 ActivityContext context2 = new ActivityContext("0618"); double money0618 = context2.getDues(money); System.out.println("618大促,应付款:" + money0618); // 双十一 ActivityContext context3 = new ActivityContext("1111"); double money1111 = context3.getDues(money); System.out.println("双十一活动,应付款:" + money1111); } }
最终输出结果
正常时期,应付款:600.0 618大促,应付款:599.0 双十一活动,应付款:300.0
总结
优点
1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好
缺点
1、策略类会增多。 子类5个以上就不推荐这种模式了。 2、所有策略类都需要对外暴露。