定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替代。本模式使得算法可独立于使用它的客户而变化!
痛点
策略模式可以很好解决众多if问题
如以下:
package com.tao.YanMoDesignPattern.Strategy.notPattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 价格管理,完成计算向客户所报价格的功能* @Version 1.0**/
public class Price {public double quoto(double goodsPrice,String customerType){if ("普通客户".equals(customerType)){System.out.println("对于新客户或者普通客户,没有折扣!");} else if ("老客户".equals(customerType)) {System.out.println("对于老客户,一律折扣5%!");return goodsPrice*(1-0.05);} else if ("大客户".equals(customerType)) {System.out.println("对于大客户,一律折扣10%!");return goodsPrice*(1-0.1);}return 0.0;}
}
先看一下标准的策略模式如何实现
上层接口,定义好行为
package com.tao.YanMoDesignPattern.Strategy.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 策略,定义算法的接口* @Version 1.0**/
public interface Strategy {public void algorithmInterface();
}
package com.tao.YanMoDesignPattern.Strategy.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class ConcreteStartegbA implements Strategy{@Overridepublic void algorithmInterface() {// 具体的算法实现}
}
package com.tao.YanMoDesignPattern.Strategy.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class ConcreteStartegbB implements Strategy{@Overridepublic void algorithmInterface() {// 具体的算法实现}
}
package com.tao.YanMoDesignPattern.Strategy.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class ConcreteStartegbC implements Strategy{@Overridepublic void algorithmInterface() {// 具体的算法实现}
}
核心实现
package com.tao.YanMoDesignPattern.Strategy.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 上下文对象,通常会持有一个具体的策略对象* @Version 1.0**/
public class Context {// 持有一个具体的策略对象private Strategy strategy;/*** 上下文对客户端提供的操作接口,可以有参数和返回值*/public void contextInterface(){// 通常会转调具体的策略对象进行算法运算strategy.algorithmInterface();}
}
问题应用策略模式来解决
package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 策略,定义计算报价算法的接口* @Version 1.0**/
public interface Strategy {/*** 计算应报的价格* @param goodsPrice* @return 计算出来的,应给客户的报价*/public double calcPrice(double goodsPrice);
}
package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class OldCusomerStategy implements Strategy {@Overridepublic double calcPrice(double goodsPrice) {System.out.println("老客户,5%折扣");return goodsPrice*(1-0.05);}
}
package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class NormalCusomerStategy implements Strategy {@Overridepublic double calcPrice(double goodsPrice) {System.out.println("普通客户,没有折扣");return goodsPrice;}
}
package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class LargeCusomerStategy implements Strategy {@Overridepublic double calcPrice(double goodsPrice) {System.out.println("大客户,10%折扣");return goodsPrice*(1-0.1);}
}
package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 价格管理,主要完成计算向客户所报价格的功能* @Version 1.0**/
public class Price {/*** 持有一个具体的策略对象*/private Strategy strategy = null;/*** 构造方法,传入一个具体的策略对象* @param strategy*/public Price(Strategy strategy) {this.strategy = strategy;}/*** 报价,计算客户的报价* @param goodsPrice 商品销售原价* @return 计算出来的,应该给客户的保教*/public double quote(double goodsPrice){return this.strategy.calcPrice(goodsPrice);}}
测试类
package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class Client {public static void main(String[] args) {// 1、选择并创建需要使用的策略对象Strategy strategy = new LargeCusomerStategy();// 2、创建上下文Price ctx = new Price(strategy);//3、计算报价double quote = ctx.quote(1000);System.out.println("向客户报价:"+quote);}}
别提有多么舒服,只要改变实现的策略就可以进行逻辑的切换!
策略模式的中心不是如何实现算法,而是如何组织,调用这些算法, 从而让程序结构更灵活,具有更好的维护性和扩展性。
经典的策略模式调用顺序
除此之外还可以解决:容错问题(上传文件是中途失败,下次要如何恢复到失败的问题。实现模板方法模式)
经典的策略模式UML图
策略模式的本质: 分离算法,选择实现
何时使用策略模式