策略模式真的像你想的那么简单么?

简介: 策略模式的使用与进阶

介绍

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。

举例:诸葛亮给了赵云三个锦囊,每个锦囊都有一个策略。选择交通工具汽车、火车、飞机都是一种策略。

注意事项:

当我们的if else中需要处理很多业务,就可以考虑使用策略模式;

如果一个系统的策略过多,就需要考虑使用混合模式,解决策略类膨胀的问题。

实现

这里以不同等级的客户购买物品时对应不同的折扣为例,先创建一个接口

publicinterfaceStrategy {
DoublecalculatePrice(Doubleprice,Integeramount);
}

具体的策略类

publicclassGeneralCustomerimplementsStrategy {
@OverridepublicDoublecalculatePrice(Doubleprice, Integeramount) {
returnprice*amount;
    }
}
publicclassSilverCustomerimplementsStrategy {
@OverridepublicDoublecalculatePrice(Doubleprice, Integeramount) {
returnprice*amount*0.99;
    }
}
publicclassGoldCustomerimplementsStrategy {
@OverridepublicDoublecalculatePrice(Doubleprice, Integeramount) {
returnprice*amount*0.97;
    }
}

创建 Context 类。上下文并不执行任务, 而是负责与具体的策略类交互。这就好比出行工具有汽车、火车、飞机,但是谁去开火车?就是这个context

publicclassContext {
privateStrategystrategy;
publicContext(Strategystrategy){
this.strategy=strategy;
 }
publicDoubleexecuteStrategy(Doubleprice,Integeramount){
returnstrategy.calculatePrice(price, amount);
 }
}

使用

publicclassStrategyDemo {
publicstaticvoidmain(String[] args) {
doubletotalPrice=0;
Contextcontext=newContext(newGeneralCustomer());
totalPrice=context.executeStrategy(15.0, 2);
System.out.println(totalPrice);
Contextcontext1=newContext(newSilverCustomer());
totalPrice=context1.executeStrategy(15.0,2);
System.out.println(totalPrice);
Contextcontext2=newContext(newGoldCustomer());
totalPrice=context2.executeStrategy(15.0, 2);
System.out.println(totalPrice);
    }
}

问题

1、还是要去if else 判断客户的等级然后决定使用哪种策略,如何解决这个问题?

2、策略类会增多,业务逻辑分散到各个实现类中,而且没有一个地方可以俯视整个业务逻辑

扩展

策略工厂模式

上一篇我们说到的工厂模式,我给一个标识,由工厂帮我创建对应的产品,那么结合到这里是不是就可以解决上述问题? 我给工厂一个客户等级标识,它会给你对应的策略。

创建策略工厂,Context类就用不上了:

publicclassStrategyFactory {
publicstaticStrategyexecute(IntegerlevelCode){
Strategystrategy=null;
switch (levelCode){
case1:
strategy=newGeneralCustomer();
break;
case2:
strategy=newSilverCustomer();
break;
case3:
strategy=newGoldCustomer();
break;
default:
thrownewIllegalArgumentException("客户等级错误");
        }
returnstrategy;
    }
}

使用

publicclassStrategyDemo {
publicstaticvoidmain(String[] args) {
//接口参数获取用户等级 传给策略工厂即可Strategygeneral=StrategyFactory.execute(1);
general.calculatePrice(15.0,2);
    }
}

如上我们可以解决第一个问题,那么第二个问题又该如何解决,策略类膨胀会导致项目非常臃肿。

Map+函数式接口

此时我们把上诉的策略类全部作为方法

@ServicepublicclassCustomerStrategyService {
publicDoublegeneralCustomer(Doubleprice, Integeramount) {
returnprice*amount;
        }
publicDoublesilverCustomer(Doubleprice, Integeramount) {
returnprice*amount*0.99;
        }
publicDoublegoldCustomer(Doubleprice, Integeramount) {
returnprice*amount*0.97;
        }
    }
Map+Function优化@ServicepublicclassPriceService {
@AutowiredprivateCustomerStrategyServicecustomerStrategyService;
@FunctionalInterfaceinterfaceCalculateFunction<A,B>{
publicDoublecalculate(Aa,Bb);
    }
privatefinalMap<Integer, CalculateFunction<Double,Integer>>strategyMap=newHashMap<>();
/*** 初始化策略*/@PostConstructpublicvoidinitDispatcher(){
strategyMap.put(1,(price,amount) ->customerStrategyService.generalCustomer(price,amount));
strategyMap.put(2,(price,amount) ->customerStrategyService.silverCustomer(price,amount));
strategyMap.put(3,(price,amount) ->customerStrategyService.goldCustomer(price,amount));
    }
publicDoublecalculatePrice(IntegercustomerLevel,Doubleprice,Integeramount){
CalculateFunction<Double, Integer>function=strategyMap.get(customerLevel);
//这里防止客户等级没找到匹配的,可以使用断言来判断从而抛出统一异常returnfunction.calculate(price,amount);
    }
}

搞个接口试试

@RestControllerpublicclassTestController {
@AutowiredprivatePriceServicepriceService;
@RequestMapping("/calculatePrice")
publicDoublecalculatePrice(IntegercustomerLevel,Doubleprice,Integeramount){
returnpriceService.calculatePrice(customerLevel, price, amount);
    }
}

总结

少于4种情况且每种情况对应的业务逻辑不复杂那肯定首选if else,

有4-6种情况且业务逻辑不复杂,建议使用switch case

业务逻辑复杂的情况下,可使用策略工厂模式或者Map+Function,自行选择。

相关文章
|
2月前
|
设计模式 算法 搜索推荐
策略模式的小记
本文介绍了策略模式的概念、结构和使用场景,并通过支付系统的例子展示了如何使用策略模式来动态选择不同的支付策略,包括定义支付策略接口、实现具体的支付策略类、创建上下文类以及在客户端动态选择支付策略。
策略模式的小记
|
6月前
|
算法 数据安全/隐私保护
行为型 策略模式
行为型 策略模式
34 1
|
设计模式 算法 Java
什么场景要使用策略模式,什么场景不能使用?
如果,让我来设计,我最先想到的就是策略模式。另外,我把往期面试题解析的配套文档我已经准备好,想获得的可以在我的煮叶简介中找到。那么什么场景要使用策略模式,什么场景又不应该使用策略模式呢?我们可以先来看官方对策略模式的定义。
164 0
|
前端开发
策略模式
策略模式
78 0
|
设计模式 算法
策略模式详细介绍
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列的算法,并将每个算法封装到具有共同接口的独立类中,使得它们可以互相替换。策略模式可以让算法的变化独立于使用它的客户端。
122 0
|
算法 测试技术 C#
C#策略模式
C#策略模式
70 0
|
设计模式 前端开发
关于策略模式我所知道的
关于策略模式我所知道的
87 0
|
算法 程序员 开发工具
简单说说我对策略模式的了解
简单说说我对策略模式的了解
87 0
|
设计模式 算法
我学会了,策略模式
策略模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。
123 0
我学会了,策略模式