今天开始研究并记录下自己项目中设计模式的应用。
策略模式
1. WHAT -- 什么是策略模式(Strategy)
定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
比较难懂,下面我会用一个实际的例子来解释一下。
2. WHEN -- 什么情况下使用策略模式
现在我的项目中有个扫码功能需要实现。
扫码功能需求:
- 应用中的扫码功能有多个入口,分别为首页右上角、其他一级界面、 二级界面。
- 二级界面扫码需要实现:功能A,二维码无效提醒
- 其他一节界面扫码需要实现:功能B,二维码无效提醒
- 首页右上角扫码需要实现:功能A、功能B、功能C,二维码无效提醒
初版设计方案
一个公共扫码界面:进入界面时需要携带扫码入口参数,比如首页key、二级界面key等等
一个处理扫码结果的业务逻辑类:
2.1. 通过
if-else对入口参数进行判断2.2. 对扫码结果进行对应入口所需要实现的功能逻辑处理 代码实现大概就是下面这个样子:
...
if (from == ScanFrom.home){
if (handleA(scanResult)) {
...
} else if (handleB(scanResult)) {
...
} else if (handleC(scanResult)) {
...
} else {
handleInvalidScanResult();
}
} else if (from == ScanFrom.detail) {
if (handleA(scanResult)) {
...
}
} else if (from == ScanFrom.my) {
if (handleB(scanResult)) {
...
}
}
...
大家会看到上面嵌套了2层if-else,如果需要在处理结果中再进行判断,则会嵌套更多层。
这样写有很多不好的地方:
1、多层嵌套后,即使封装成了方法也会使得这个逻辑处理类显得异常庞大
2、后期需要添加新的扫码入口时,就需要在后面继续添加
else if,对于这个类来说维护起来很不方便3、违反了
“开闭原则”,后期如果需要在某个或某几个入口添加新功能的时候,又是一笔巨大的工作量
所以,为了解决1(大量if-else嵌套)、2(大量并列if-else条件判断)、3(违反‘开闭原则’)这两个问题,我选择使用策略模式来进行优化。
3. HOW -- 怎么使用策略模式
3.1 创建策略抽象类(ScanScene),把具体的处理场景给抽象出来;
3.2 创建具体策略类(ScanSceneHome、ScanSceneDetail等等),实现每个场景中扫码的具体逻辑;
3.3 创建环境类(ScanStrategyManager),在类中添加具体的ScanScene具体策略类,然后实现根据传入的scene不同,选择不同的ScanScene来进行处理。
3.4 使用时,把对应场景的
scene当作key,把具体策略ScanSceneXxx当作value保存在 ScanStrategyManager的scanSceneMaps中,比如:scanSceneMaps.add('home', >ScanSceneHome())3.5 在其他类中使用时,可以直接调用ScanStrategyManager(环境类)中的handleScanResult方法,通过传入
scene(场景参数)和scanResult(扫码结果参数)来对扫码结果进行相应场景的处理。
4. WHY -- 为什么策略模式能够解决上面的3个问题
1、嵌套if-else: 由于把并列的
if-else中的内容都抽取成具体策略类,所以在ScanStrategyManager(环境类)中的子if-else都不存在了,只保留了一层场景if-else判断2、并列if-else: 由于把具体场景类通过
场景(key)-具体策略类(value)的方式保存到map中,使用时根据传入的scene参数作为key,直接从map中获取到对应的值,进而取消了大量的并列if-else,后续在新增场景的时候,也不用去在添加if-else,只需要在map中添加对应的键值对即可。3、开闭原则: 由于使用了map的方式来保存具体策略类,所以在后续的开发中,不需要对该类进行修改,只需要通过map的add方法即可添加具体的策略类