引言
策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时选择算法的一种方法,从而在不同情境下能够更灵活地改变对象的行为。该模式的核心思想是将不同的算法封装成独立的策略类,使得这些算法可以互相替换,而客户端代码不需要知道具体使用哪种算法,从而降低了代码之间的耦合性。
Define a family of algorithms,encapsulate each one,and make them interchangeable.(定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。)
策略模式demo (IKun 粉丝见面会策略)
情景再现,IKUN 终于忙完了给每个小黑子都发了律师函,决定搞一个粉丝见面会。经纪人根据IKUN的才艺制定了三个策略:打篮球、Rap 表演、唱歌跳舞。制定好了流程,随便IKUN选择哪个策略粉丝见面会流程都能正常进行~
非常符合策略设计模式的应用场景。我们一起来看看代码实现~
// 策略抽象接口,必须要 show 一下
interface IKunFansInteractInterface {
show(msg: string):void;
}
// IKun 粉丝见面会有三个策略
// 如果下雨,那就室内打篮球
class BasketballStrategy implements IKunFansInteractInterface {
constructor() {
// 初始化,穿上背带裤
}
show(msg: string) {
console.log('我是 IKUN, 我为 NBA 代言~', msg);
}
}
// 给大家表演一首 Rap
class RapStrategy implements IKunFansInteractInterface {
constructor() {
// 准备好破洞牛仔裤
}
show(msg: string) {
console.log('大家跟我一起 Rap~ 嘿嚯 ~ 轰')
}
}
// 给大家跳个舞
class DanceAndMusicStrategy implements IKunFansInteractInterface {
show(msg: string) {
console.log('给大家表演才艺~ 唱跳');
}
}
class IKunContext {
// 今天坤坤时间不够,晚上有安排了,一次只能安排一个粉丝见面会
private strategy: IKunFansInteractInterface;
constructor(strategy: IKunFansInteractInterface) {
this.strategy = strategy;
}
// IKUN 开始表演
public run() {
this.strategy.show('IKUN');
}
}
// IKUN 说了随便哪个都行,我是经纪人,别说我不公平。随机转个骰子,转到谁就是谁~
function main() {
console.log('____________________________')
const random = Math.random();
// 打篮球
if (random < 0.33) {
const runner = new IKunContext(new BasketballStrategy());
runner.run();
return;
}
// rap
if (random > 0.66) {
const runner = new IKunContext(new RapStrategy());
runner.run();
return;
}
const runner = new IKunContext(new DanceAndMusicStrategy());
runner.run();
}
main();
main();
main();
出色的完成了粉丝见面会,第二天经纪人收到了IKUN 的律师函~ 不用同情他,我们来看看策略模式的组成。
策略模式的组成
策略模式使用的就是面向对象的继承和多态机制,非常容易理解和掌握。主要有三个部分:
- Context 封装,也就是这里的 IKunContext 。一般叫做上下文角色,封装上起到作用是承上启下,屏蔽高层模块对底层策略模块的直接访问。
- Strategy 抽象策略。接口定义,也就是这里的 IKunFansInteractInterface。抽象策略定义策略中的规范,每个策略结构上要一致。
- 具体的策略实现,抽象策略的具体实现。BasketballStrategy、RapStrategy、DanceAndMusicStrategy 爱坤三板斧就是具体的策略实现。
策略模式优点
- 算法可以自由切换。每个实现自抽象策略的类,都可以对外提供自由切换的能力【IKUN 打篮球、Rap 两个策略可以随便切换,对本次的粉丝见面会没有影响。换到支付模式也一样:微信支付、支付宝支付、现金支付对于购物流程都是一致的~策略方式随便换】。
- 扩展性好。太明显了,现在要扩展一个新的策略比较简单,扩展一个类实现抽象策略接口即可。比如 IKUN 经过一年半的练习,终于掌握了钢管舞,那就继承一下 IKunFansInteractInterface , show 函数里面给大家表演钢管舞即可。
策略模式的缺点
- 策略类数量增多。每个策略就是一个类,复用的可能性非常小,类数量变多【所以如何控制策略的粒度就是设计中需要衡量的点~】。
- 所有的策略类都需要对外暴露。上层模块必须知道有哪些策略类才能决定使用哪一个策略。这个和迪米特法则【不该知道的不打听~】相悖。解决方案就是与其他设计模式一同配合:工厂方法模式、代理模式或者享元模式【IKUN 下期会和大家再见面的,请期待~】。
策略模式的使用场景
- 算法需要自由切换
- 多个类之间只是存在算法或行为上稍有不同【其实是我们设计之前需要考虑的,复杂的判断条件,如何拆分成不同的算法策略~】
- 需要屏蔽算法规则的场景。具体的逻辑我们可以不用管,只要告诉我支不支持微信支付,我上层调用微信支付即可,不需要知道微信支付的实现逻辑。
总结
策略模式,比较简单容易组织代码。基于解决它的缺点,通常会和工厂方法模式来实现策略类的申明,称之为混合模式~混编模式?
IKUN 到这里就要和大家说拜拜了~ 还得回家发律师函去~ 下期再见