你看那里有只小鸭哟,你看那里又只小鸭哟~小鸭嘎嘎嘎-ga-哟~小鸭嘎嘎嘎-ga-哟~

矮油我艹,居然被这神曲给洗脑了。现在一看到小动物就莫名其妙的会哼唱起来,那么问题来了,长颈鹿怎么叫?“好长~好长~”是这样叫的么?这个问题真的很逗逼耶……

好啦,不扯淡了,原归正传。我要讲的主题就是小鸭子!哦sorry,准确的应该说是策略模式。因为策略模式中最经典例子莫过于鸭子模型的设计啦。之前有很多大神都写过文章讲解,讲得都非常深入和细致。但我这篇文章中,只是大略的以个人理解思维去阐述一个故事,如有讲得不足之处还望见谅。

故事的开头是这样,会议上老板说:“最近接了个玩具厂的项目,要我们做个鸭子程序。没啥需求,就是要有大黄鸭、青头鸭、丑小鸭、唐老鸭……它们都会叫会飞!好啦,这种小项目就交给刚来实习的小林去做吧。”我胸有成足的接下了这个任务,心想这小儿科so easy ~

先做个鸭子接口:

public interface Ducks {/*** 外貌*/abstract void display();/*** 叫声*/abstract void quack();/*** 飞行*/abstract void fly();/*** 游泳*/public void swim();}

在写鸭子接口的实现类:

public class Green implements Ducks {@Overridepublic void display() {System.out.println("我是青头鸭~~");}@Overridepublic void quack() {System.out.println("gaga~叫声很好听");}@Overridepublic void fly() {System.out.println("飞得老高了我~~");}@Overridepublic void swim() {System.out.println("游的老快了~");}}

…………

最后呢,在 if-else if- 来判断我要调用的是那个模型的鸭子:

public void selectDuck(String type) {if (type.equals("yellow")) {Ducks duck = new Green();duck.quack();} else if (type.equals("green")) {Ducks duck = new Yellow();duck.fly();}}

恩,很快的项目完成了。我高高兴兴的把第一版本给提交了。老板哪会管你是如何实现的,只要你能完成预期的功能效果就ok。正当我还在得意洋洋之时,问题就来了。玩具厂的说要让有的鸭子不会飞,有的鸭子不会叫,有的鸭子不仅会叫还要回唱歌,唱歌还不够,要给鸭子分等级,等级高的还会讲故事……

呵呵,我勒个擦!那我岂不是要在每个鸭子接口和实现类中添加好多方法?还得在调用selectDuck中多做好多else if判断?今天改了这些歌需求,万一明天又突然给我加过别的需求,我不是又要重新改一遍代码了么?忧伤的我,一筹莫展,对着电脑发呆。我该怎么办才好呢,让我别每次都改动原来写好的代码,有新的需求的时候只要多添加个类就好了?

“今天怎~~~么不开心~?”老周问我:“不用担心,时间会给你答案~我的滑板鞋时尚时尚最时尚~”我吧事情跟老周详细讲了一遍后,老周笑道:“骚年,你还太年轻!这完全可以用策略模式去解决啊!”

于是乎老周就开始很装逼的给我云云:

一、所谓的策略模式呢就是:

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。“亲,您能说的直白点吗?”“哦,抱歉。我向来都是这么专业的。说白了,就是你不是有很多鸭子吗?每个鸭子要有不同的功能,比如说飞行的算法,叫声的算法,游泳的算法,你都统统把它们一个一个的封装起来。到时候具体需要什么样的鸭子,就给客户自己去选择咯。”

二、那到底要怎么去实现呢?

1. 对策略对象定义一个公共接口(FlyBehavior、QuackBehavior……接口;把所有的行为都做成接口方便以后对策略的扩展)
    2. 编写具体策略类,该类实现了上面的接口(FlyNoWay、FlyWithWings、Quack、MuteQuack……以后要是有什么新功能,就只需要去实现行为接口,添加新的策略类咯)
    3. 在使用策略对象的类(即:环境角色)中保存一个对策略对象的引用(Duck;最为关键的就是这个引用对象了,既然我们是要创建鸭子,当然就要用鸭子去引用策略啦。)
    4. 在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值(引用的小技巧就是用传说中的"组合")
    5. 客户端进行调用 (调用不同的鸭子时就分配给它相应的策略咯)

扯了半天还是云里雾里的感觉。老周啊,你妹图扯个蛋呀!结果老周不服气,马上画了张图:

抽象策略角色:策略类,通常由一个接口或者抽象类实现。

具体策略角色:包装了相关的算法和行为。

环境角色:持有一个策略类的引用,最终给客户端用的。

三、终于开窍了,老周啊,你真是中国好同事哟。按照老周说的硬是把代码给敲出来了:

首先,鸭子喊叫和飞行的公共接口。

package com.strategy.quack;/*** 鸭子叫的接口* @author linhy**/
public interface QuackBehavior {public void quack();
}
package com.strategy.fly;/*** 鸭子飞行接口* @author linhy**/
public interface FlyBehavior {public void fly();}

然后,就是这两个接口的实现类。

package com.strategy.quack;/*** 会叫的鸭子类* @author linhy**/
public class Quack implements QuackBehavior {@Overridepublic void quack() {System.out.println("嘎嘎嘎~听得到我在叫你么……");}}
package com.strategy.quack;/*** 不会叫的鸭子类* @author linhy**/
public class MuteQuack implements QuackBehavior {@Overridepublic void quack() {System.out.println("我是一只安静的没鸭子,不会叫~");}}
package com.strategy.fly;/*** 会飞的鸭子类* @author linhy**/
public class FlyWithWings implements FlyBehavior {@Overridepublic void fly() {System.out.println("我是在用翅膀飞翔,带你装B,带你飞……");}}
package com.strategy.fly;/*** 不会飞的鸭子类* @author linhy**/
public class FlyNoWay implements FlyBehavior {@Overridepublic void fly() {System.out.println("超人不会飞,鸭子也不会飞……");}}

恩,策略都已经准备好了,接下来要开始引用它了。用什么引用?当然是鸭子啦!但是,鸭子又有好多种类型的哦,所以要先把鸭子抽象下,方便以后再创建新类型鸭子……

package com.strategy.duck;import com.strategy.fly.FlyBehavior;
import com.strategy.quack.QuackBehavior;/*** 鸭子抽象类* @author linhy**/
public abstract class Duck {//------------组合方式引用鸭子策略--------------------//引入鸭子的飞行行为对象private FlyBehavior flyBehavior;//引入鸭子的叫唤行为对象private QuackBehavior quackBehavior;//通过子类来设置鸭子的飞行行为public void setFlyBehavior(FlyBehavior flyBehavior) {this.flyBehavior = flyBehavior;}//通过子类来设置鸭子的叫唤行为public void setQuackBehavior(QuackBehavior quackBehavior) {this.quackBehavior = quackBehavior;}public void performFly() {flyBehavior.fly();}public void performQuack() {quackBehavior.quack();}// 鸭子的外貌不一样哦,所以我要抽象~abstract void display();//鸭子都会游泳哦,游泳的方式就暂且都一样吧……public void swim() {System.out.println("All ducks float, even decoys");}}

抽象的鸭子已经设计好咯,就要写具体继承它的子类咯。

package com.strategy.duck;import com.strategy.fly.FlyBehavior;
import com.strategy.quack.QuackBehavior;/*** 青头鸭* @author linhy**/
public class GreenDuck extends Duck {//通过构造方法来设置引用的鸭子对象的行为public GreenDuck(FlyBehavior flyBehavior, QuackBehavior quackBehavior) {super.setFlyBehavior(flyBehavior);super.setQuackBehavior(quackBehavior);}@Overridepublic void display() {System.out.println("我是一只美丽动人的青头鸭~~");}}
package com.strategy.duck;import com.strategy.fly.FlyBehavior;
import com.strategy.quack.QuackBehavior;/*** 小黄鸭* @author linhy**/
public class YellowDuck extends Duck {//通过构造方法来设置引用的鸭子对象的行为public YellowDuck(FlyBehavior flyBehavior, QuackBehavior quackBehavior) {super.setFlyBehavior(flyBehavior);super.setQuackBehavior(quackBehavior);}@Overridepublic void display() {System.out.println("我是一只美丽动人的小黄鸭~~");}}

这下鸭子模型准备好了,策略方法也写好了。那么就开始调用测试下看看呗。

package test;import com.strategy.duck.GreenDuck;
import com.strategy.duck.YellowDuck;
import com.strategy.fly.FlyNoWay;
import com.strategy.fly.FlyWithWings;
import com.strategy.quack.MuteQuack;
import com.strategy.quack.Quack;/*** 给不同类型的鸭子设置不同行为的策略* @author linhy**/
public class TestDuck {public static void main(String[] args) {//设置小黄鸭会飞和叫YellowDuck yellowDuck = new YellowDuck(new FlyWithWings(), new Quack());//设置青头鸭不会飞,也不会叫GreenDuck greenDuck = new GreenDuck(new FlyNoWay(), new MuteQuack());System.out.println("***************************************");yellowDuck.display();yellowDuck.performFly();yellowDuck.performQuack();yellowDuck.swim();System.out.println("*****************************************");greenDuck.display();greenDuck.performFly();greenDuck.performQuack();greenDuck.swim();}}

结果是这样的:

嘿嘿,是这样的哦。别看上去好像感觉要写那么多类啊,接口啊……感觉好麻烦。当你要去维护,去新增功能的时候,你就会体会到一个好的设计模式是多麽的方便。好比,下次老板要是提出:小林,我要一只超级鸭(多功能的鸭子),会讲故事、会跳舞……我只需要新增个些策略和超级鸭子类,鸭子抽象类稍微修改下就可以。不要像以前那种蠢方法,耦合度太高,要修改太多地方,代码看上去也不整洁。

老周最后来了一句:图羊图森破~。不装逼你会死呀,心里暗骂到。但还是忘分感谢……毕竟成长的道路上就是要在不断的挫折中学习。

结语:

啧啧,故事终于讲完了,我知道自己讲的相当烂,有好多东西没说清。特附上一篇策略模式的好文章:《研磨设计模式之策略模式》

转载于:https://blog.51cto.com/linhongyu/1584007

鸭子在叫哟,嘎嘎嘎---策略模式相关推荐

  1. 策略设计模式_设计模式之策略模式总结

    再上一篇文章<设计模式之策略模式>中,我们通过模拟鸭子项目,了解了什么是策略模式,怎么使用策略模式.本文将通过鸭子项目的学习,对策略模式进行总结. 策略模式: 分别封装行为接口,实现算法族 ...

  2. 设计模式随笔系列:鸭子-策略模式(Strategy)

    鸭子-策略模式(Strategy) 前言 万事开头难,最近对这句话体会深刻!这篇文章是这个系列正式开始介绍设计模式的第一篇,所以肩负着确定这个系列风格的历史重任,它在我脑袋里默默地酝酿了好多天,却只搜 ...

  3. 设计模式随笔系列:鸭子-策略模式(Strategy)[原]

    原文地址为: 设计模式随笔系列:鸭子-策略模式(Strategy)[原] 鸭子-策略模式(Strategy) 前言 万事开头难,最近对这句话体会深刻!这篇文章是这个系列正式开始介绍设计模式的第一篇,所 ...

  4. 鸭子-策略模式(Strategy)[原]

    鸭子-策略模式(Strategy) 前言 万事开头难,最近对这句话体会深刻!这篇文章是这个系列正式开始介绍设计模式的第一篇,所以肩负着确定这个系列风格的历史重任,它在我脑袋里默默地酝酿了好多天,却只搜 ...

  5. 打印鸭子戏水java,《Head first设计模式》学习笔记 #8211; 策略模式,

    <Head first设计模式>学习笔记 – 策略模式, 策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 假设有一个模拟鸭子的游戏,游 ...

  6. 设计模式解读之一: 策略模式——鸭子游戏

    设计模式解读之一: 策略模式--鸭子游戏 当我们掌握了Java的语法,当我们了解了面向对象的封装.继承.多态等特性,当我们可以用Swing.Servlet.JSP技术构建桌面以及Web应用,不意味着我 ...

  7. Java设计模式(备忘录模式-解释器模式-状态模式-策略模式-职责链模式)

    Java设计模式Ⅶ 1.备忘录模式 1.1 备忘录模式概述 1.2 代码理解 2.解释器模式 2.1 解释器模式概述 3.状态模式 3.1 状态模式概述 3.2 代码理解 4.策略模式 4.1 策略模 ...

  8. 【HeadFirst 设计模式总结】1.策略模式

    1.书中举了一个鸭子类的设计,有些会飞或者会叫,有些不会飞可能也不会叫,用继承则导致不该有的功能通过继承而继承了下来,使用接口则代码无法做到最大程度的重用.进而引出设计原则1:找出应用中可能需要变化之 ...

  9. 设计模式(一)————策略模式(张三的故事??)

    引言 当我们完成一个复杂的业务中常常会面临一个问题:针对一个对象的某个行为,不同的情境下有不同的处理方式: 就比如今天我要去上班,那么我需要以哪种交通方式去上班呢?可以有下面几种选择: 步行 公交 地 ...

最新文章

  1. 巧用CSS的RevealTrans滤镜
  2. 以太网、局域网、互联网区别
  3. 机器学习梯度下降法举例
  4. 我肝了一个月,给你写出了这本Java开发手册。
  5. python条件表达式:多项分支,双向分支
  6. 基于Spring boot + Mybatis +Netty 实现前后端分离的聊天App,部署到阿里云线上服务器...
  7. 长期价值三重进阶,同程艺龙加速“破局”OTA
  8. 大人的世界啊,全是屁股!
  9. Hibernate继承(2)子类属性生成在自己的一张表中,父类的属性一张表
  10. 添加lua_C++/Lua高级交互
  11. 分布式消息规范 OpenMessaging 1.0.0-preview 发布 1
  12. 长安清酒·花酿清酒一瓣心醉的甜香
  13. 特征点匹配——SIFT算法详解
  14. 深信服 VDS设备烤机
  15. 理解es6中的暂时性死区
  16. 首款国产7纳米GPGPU芯片在上海问世
  17. 耳机重装系统后服务器坏了,Win7重装后耳机没声音|重装系统后耳机没声音怎么办?...
  18. python函数中self的作用_在Python中self的用途是什么?
  19. 如何使用python进行自动网上考试
  20. GIS初学者,最新OpenLayers WMTS 天地图,OpenLayers加载天地图、调用天地图WMTS示例、tianditu、EPSG:3857、EPSG:4326

热门文章

  1. TCP/IP入门(2) --网络层
  2. 天天生鲜项目——我的购物车页
  3. 每日算法面试题,大厂特训二十八天——第九天(位运算)
  4. 云端办公后,协同软件也能轻松做好项目管理
  5. 用input标签 文件,多文件上传
  6. Precision(精准率、查准率)和Recall(召回率、查全率)的应用场景
  7. 用python做视觉检测系统_教你用 Python 做一个物体检测系统
  8. 小程序开发+weuiwxss
  9. 奇瑞a3中控按键图解_奇瑞A3使用说明
  10. 【IDEA 报错 ERROR 16720 --- [ restartedMain] o.a.coyote.http11.Http11NioProtocol : Failed to sta】