普遍定义

定义个一个算法族, 各个算法的实现可以相互替换, 算法的实现和具体的算法使用场景隔离

策略模式的进化

【产品】:我需要一堆鸭子,红色的,绿色的,黑色的,还要会飞!还要会叫!

【开发】:明白,秒秒钟搞定,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里我喜欢玩奶妈,因为奶妈可以加血,那么在英雄技能设计上,加血是一种行为,具体的细节每个英雄都不一样,这就是策略模式的一种体现

  • 比如支付场景中我们会抽取支付信息中的订单,状态,付款人,金钱等等信息,但是支付的细节可以是支付宝也可以是微信

真假策略模式

写这篇文章的时候,在网上也查询了很多资料,发现大家的策略模式总有一些细枝末节不一样的地方,接下来会展示一部分代码,大家可以主观来判断一下它是否属于策略模式,是否可以用其他设计模式代替

/*** 网络玄幻小说的故事梗概接口* 固定的一些套路* 策略模式:网络小说的固定套路*/
public interface Synopsis {/*** 穷困潦倒的开始*/void badStart();/*** 突然有天遇到神人/捡到神器,实力大涨*/void adventure();/*** 在一场战斗中以弱胜强*/void winABattle();/*** 从此飞速成长*/void growFast();/*** 组团刷怪,经历九死一生(主角怎么也死不了)*/void manyFights();/*** 最终功成名就,妻妾成群*/void succeed();/*** 组合起来就是小说内容*/void getContent();
}/*** 故事 A ,恶魔法则*/
public class StoryA implements Synopsis {// 实现省略
}/*** 故事 B ,诛仙*/
public class StoryB implements Synopsis {// 实现省略
}

策略选择类:

/*** 策略选择类*/
public class WriteNovel {private Synopsis mSynopsis;     //故事梗概private String mMainActorName;  //主角名称/*** 梗概、内容都差不多确定后,换个名称就是另一部小说* @param mainName*/public WriteNovel(String mainName){switch (mainName){case "张小凡":mSynopsis = new StoryB(mainName);break;case "杜维":mSynopsis = new StoryA(mainName);break;default:mSynopsis = new StoryB(mainName);break;}}/*** 获取小说内容*/public void getNovelDetail(){mSynopsis.getContent();}
}

最后

附上策略模式的UML图

然后再说一个暖心小故事~

在2020年5月6日的时候,我发现了掘金的一个BUG,整个界面都加载不出来(已经修复啦~)

第二天我找到了掘金首席产品体验官优弧小姐姐,跟她积极反馈了BUG,同时小小的推荐了一下子自己的文章,然后发了许久的一篇文章就这样再一次上了热门第一名,实证如下(开心到爆炸):


【一起学系列】之策略模式:好多鸭子啊相关推荐

  1. 设计模式初学者系列-策略模式 -------为什么总是继承

    设计模式初学者系列-策略模式                                                 -------为什么总是继承 模板方法的延续 这篇稿子是基于我的前一篇模板 ...

  2. 从零开始单排学设计模式「策略模式」黑铁 II

    阅读本文大概需要 1.7 分钟. 本篇是设计模式系列的第三篇,虽然之前也写过相应的文章,但是因为种种原因后来断掉了,而且发现之前写的内容也很渣,不够系统.所以现在打算重写,加上距离现在也有一段时间了, ...

  3. 大前端晋级系列之-策略模式

    谨代表自己的理解,有错误欢迎指出! 因为有jQuery的源码分析系列,所以尽量走jQuery的设计风格,便于理解. 为什么要使用策略模式? 举个例子,企业或者个人都要纳税,但是不同的国家税点自然是不一 ...

  4. 橘子学设计模式之策略模式

    策略模式 1.简介 俗话说:条条大路通罗马.在很多情况下,实现某个目标的途径不止一条,例如我们在外出 旅游时可以选择多种不同的出行方式,如骑自行车.坐汽车.坐火车或者坐飞机,可根据实 际情况(目的地. ...

  5. 换个姿势学设计模式:策略模式

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源:公众号「闻人的技术博客」 前言 前段时间,接到一个 ...

  6. 【设计模式实践系列】策略模式应用订单折扣方案

    策略模式 策略模式指的是一个类的行为或其算法可以在运行时更改,在不同的场景中,有不同的实现算法. 意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换. 主要解决:在有多种算法相似的情 ...

  7. 图解Java设计模式学习笔记——行为型模式(模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式)

    一.模板方法模式(模板模式)--钩子方法 1.需求-豆浆制作问题 编写制作豆浆的程序,说明如下: 制作豆浆的流程选材-->添加配料-->浸泡-->放到豆浆机打碎. 通过添加不同的配料 ...

  8. 从零开始单排学设计模式「代理模式」青铜 III

    阅读本文大概需要 3.2 分钟. 本篇是设计模式系列的第六篇,虽然之前也写过相应的文章,但是因为种种原因后来断掉了,而且发现之前写的内容也很渣,不够系统. 所以现在打算重写,加上距离现在也有一段时间了 ...

  9. Carson带你学设计模式:模板方法模式(Template Method)

    前言 今天Carson来全面总结最常用的设计模式 - 模板方法模式. Carson带你学设计模式系列文章 Carson带你学设计模式:这是一份全面 & 详细的设计模式学习指南 Carson带你 ...

  10. 第 25 章 策略模式

    第 25 章 策略模式 1.编写鸭子项目 编写鸭子项目,具体要求如下: 有各种鸭子(比如野鸭.北京鸭.水鸭等, 鸭子有各种行为,比如叫.飞行等) 显示鸭子的信息 2.传统方案解决鸭子问题 传统方案解决 ...

最新文章

  1. 一文读懂机器学习、数据科学、人工智能、深度学习和统计学之间的区别!
  2. android字符串获取数字索引,从字符串中提取特定数据(Extract specific data from a string)...
  3. 不恰当使用read会造成服务器阻塞
  4. 领域驱动设计,让程序员心中有码(五)
  5. 使用Java流查询数据库
  6. 同事删库跑路后,我连表名都不能修改了?
  7. Python调用API接口的几种方式
  8. 基于物联网的工业分析将席卷制造业
  9. nohub java -jar xx.jar /dev/null 21 以及/dev/null是什么 21又是什么?
  10. 草根创新的狂欢——《大数据时代》对程序员的启示
  11. nginx常用配置和用法
  12. Hololens学习(三)打包编译安装HoloLens2应用
  13. 有好看的女生用的黑色壁纸吗?
  14. 嵌入式Linux系统镜像制作(基于SD卡)
  15. 用python实现等额本息
  16. 微信公众号网页授权,获取用户信息以及openid -- PHP后台
  17. 如果面试时大家都说真话
  18. Windows下Android源码下载
  19. (每日一练c++)解数独
  20. shell命令使用sed从JSON中提取指定的值

热门文章

  1. 拔丝芋头的Java学习日记--Day3
  2. BLE(9)—— 细说 Advertising
  3. 解决C:\Users\Admin\AppData\Roaming\npm\nodemon.ps1
  4. 微信小程序实现控制标题栏背景色
  5. HyperLynx(七)微带线串扰的仿真
  6. 【Luogu】P8195 小智的疑惑
  7. Unity网格变形插件的简单使用:以curve sculpt layered自由变换修改器为例
  8. C语言中时间相关函数总结
  9. 经典推荐:盛大架构师周爱民回顾职业历程,分享十项建议
  10. 职场新人收集的前辈经验