策略模式篇
标签: #Share
普遍定义
定义个一个算法族, 各个算法的实现可以相互替换, 算法的实现和具体的算法使用场景隔离
策略模式的进化
【产品】:我需要一堆鸭子,红色的,绿色的,黑色的,还要会飞!还要会叫!
【开发】:明白,秒秒钟搞定,N种鸭子只要继承了我的Duck类然后重写,就搞定一切!
public abstract class Duck {
// 颜色属性
String color;
// 飞行方法
fly();
// 呱呱叫的方法
quack();
}
Some times later…
【BOSS】:磕大头!你怎么回事!!!你能不能告诉我为什么橡皮鸭子会在天上飞!!!???
【开发】:(不敢说话,只有内心独白: 原来无脑继承会出大问题啊… 我是谁… 我在哪… 我该怎么办…)

磕大头的十万个问题
Q1. 以后还有很多奇奇怪怪的情况,谁知道老板哪天要不要让橡皮鸭也飞起来,我该怎么办?
Q2. 只用封装,继承好像不行,好像还有一个多态?
Q3. 我该怎么使用多态呢?
Q4. 我是不是可以把飞这个行为定义成接口,然后把这个接口…… 放到鸭子基类里面去!!!

核心代码
public abstract class Duck {
/**
* 飞行行为是动态的,可能会变的,因此抽成多个接口的组合,而不是让Duck类继承
*/
FlyBehavior flyBehavior;
/**
* 每个鸭子的叫声不同,抽象成接口
*/
QuackBehavior quackBehavior;
}
这下子,好像真的就解决了呢,想怎么飞就怎么飞,想怎么叫就怎么叫
遵循的设计原则
- 封装变化
- 多用组合,少用继承
- 针对接口编程,而不是针对实现编程
我之前的理解误区
大家在初学Java的时候,肯定都绕不开设计模式这一Part,那个时候我对策略模式的认知是这样的,核心代码如下:
// 不需要看全貌,就看这一段核心代码
public strategyChoose(String mainName){
switch (name){
case "A":
story = new StoryB(name);
break;
case "B":
story = new StoryA(name);
break;
default:
story = new StoryB(name);
break;
}
}
以下是错误理解:
我之前认为,策略模式,顾名思义就是定义不同的策略(即算法),然后动态的调用就好了,比如我定义A,B两种策略,然后通过Switch分支语句选择策略就可以
这样理解的错误点在于:错误的理解了策略模式的重点,而误把工厂模式的策略选择当作策略模式
现在的理解:
- 设计模式肯定有其变种,我们不需要太拘泥于条条框框而限制了自我
- 任何定义都有其普遍的理解,我们在突破自我的同时,不能完全走偏
- 所以真正的策略模式核心即:封装行为,依赖接口,组合代替继承
为什么策略模式常和工厂模式或枚举混用?
首先我们知道了策略模式最初的起源和关键点:行为或者说算法的抽象及接口的组合
那么问题来了,在我们拥有多种策略的时候,策略的数量和类型会大大增加,那么调用N种策略肯定需要一个简单的逻辑进行更好的调用,那么策略枚举,或者简单工程则会成为我们最先考虑的方式之一,也正因为如此,才会有上文中我出现的理解误区
生活中的策略模式
LOL里我喜欢玩奶妈,因为奶妈可以加血,那么在英雄技能设计上,加血是一种行为,具体的细节每个英雄都不一样,这就是策略模式的一种体现
比如支付场景中我们会抽取支付信息中的订单,状态,付款人,金钱等等信息,但是支付的细节可以是支付宝也可以是微信
最后
附上策略模式的UML图


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!