策略模式定义:
策略模式定义了一系列的算法,并将每一个算法封装起来,使每个算法可以相互替代,使算法本身和使用算法的客户端分割开来,相互独立。
策略模式的作用:就是把具体的算法实现从业务逻辑中剥离出来,成为一系列独立算法类,使得它们可以相互替换。
策略模式的着重点:不是如何来实现算法,而是如何组织和调用这些算法,从而让我们的程序结构更加的灵活、可扩展
开闭原则:
对于扩展是开放的(Open for extension)。这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。也就是说,我们可以改变模块的功能
对于修改是关闭的(Closed for modification)。对模块行为进行扩展时,不必改动模块的源代码或者二进制代码
举个例子:
现在我们要做一个报价管理的模块,简要点就是要针对不同的客户,提供不同的折扣报价
public class QuoteManager {
public BigDecimal quote(BigDecimal originalPrice,String customType){
if ("新客户".equals(customType)) {
System.out.println("抱歉!新客户没有折扣!");
return originalPrice;
}else if ("老客户".equals(customType)) {
System.out.println("恭喜你!老客户打9折!");
originalPrice = originalPrice.multiply(new BigDecimal(0.9)).setScale(2,BigDecimal.ROUND_HALF_UP);
return originalPrice;
}else if("VIP客户".equals(customType)){
System.out.println("恭喜你!VIP客户打8折!");
originalPrice = originalPrice.multiply(new BigDecimal(0.8)).setScale(2,BigDecimal.ROUND_HALF_UP);
return originalPrice;
}
//其他人员都是原价
return originalPrice;
}
}
上面存在的问题:把不同客户的报价的算法都放在了同一个方法里面,使得该方法很是庞大,此外没加一个算法就意味着要增加一种else if,违反了开闭原则
使用策略模式可以很好的解决这一问题
策略接口
1 package strategy.examp01;
2
3 // 策略接口
4 public interface IStrategy {
5 // 定义的抽象算法方法 来约束具体的算法实现方法
6 public void algorithmMethod();
7 }
具体策略实现1
1 package strategy.examp01;
2
3 // 具体的策略实现
4 public class ConcreteStrategy implements IStrategy {
5 // 具体的算法实现
6 @Override
7 public void algorithmMethod() {
8 System.out.println("this is ConcreteStrategy method...");
9 }
10 }
具体策略实现2
1 package strategy.examp01;
2
3 // 具体的策略实现2
4 public class ConcreteStrategy2 implements IStrategy {
5 // 具体的算法实现
6 @Override
7 public void algorithmMethod() {
8 System.out.println("this is ConcreteStrategy2 method...");
9 }
10 }
调用方式1:调用方调用具体的策略
//策略模式获取接口下所有实现类实例:
Map<String, IStrategy> contextBeansOfTypeMap = springUtils.getContext().getBeansByType(
IStrategy.class);
// 按key排序,遍历map集合校验活动信息
contextBeansOfTypeMap.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEachOrdered(x -> contextBeansOfTypeMap.get(x.getKey()).algorithmMethod());
调用方式2:调用某一个策略
// 获取具体实现类对象(bizName在具体实现类上已注解的形式指定,例如:@Component("ConcreteStrategy"))
IStrategy iStrategy = SpringUtils.getBeanByName(bizName, IStrategy.class);
// 调用指定实现类的方法
iStrategy.algorithmMethod();