先从简单的鸭子游戏说起

jack为公司做了一套相当牛逼的鸭子游戏,鸭子能戏水,能呱呱叫。此系统内部设计使用了标准的oo技术,设计了一个鸭子超类,并让鸭子继承此超类

去年由于公司竞争压力加剧,在为期一周的高尔夫假期兼头脑风暴之下,公司主管认为是创新的时候了,他们要在下周互联网大会上展示一些牛逼哄哄的东西振奋人心。

现在我们让鸭子能飞

主管们相信,会飞的鸭子能将竞争者远远抛在后面。在这个时候,jack拍拍胸脯说,“领导放心,这个飞鸭我一个星期就能搞定”,毕竟,我是一个oo程序员,一点问题没有。

jack在想,我只要在duck类中加上fly()方法,所有继承的鸭子就都能飞了。这是我大显身手的时候了,绽放我的oo才华吧!哈哈哈

但是,可怕的问题发生了

领导带着jack所开发的鸭子游戏上大会上演讲,许多鸭子就在屏幕上飞来飞去,台下一片笑声。在讲台上,领导很尴尬。大会结束,立马打电话给jack。

jack在电话上承认他的设计有点问题,一旦给超类加上fly()方法,所有的鸭子都能飞了,连那些不具备飞行能力的鸭子也能飞了。但是jack又想,我可以让那些不具备飞行能力的鸭子在他自己的类中覆盖fly()方法,让它什么事情也不做,这样鸭子就不能飞了。

利用接口如何?

jack意识到继承不是好的解决方法,因为他拿到领导的备忘录,里面说是以后会常常更新产品,至于怎样的需求还没有想好。jack知道了规格会常常变更,每当有新鸭子子类出现时,他就要检查所有子类的鸭子的fly()方法是否要覆盖,要是还有其他方法的话也是同样需要检查,这简直是噩梦。

所以他需要一个更清晰的方法,让某些鸭子类型可飞或可叫等功能。

于是他想了一个方法把可变的功能性方法提取出来,比如把fly()方法从超类中取出,单独设置成Flyable接口,quack()方法设置成QuackAble接口,让会飞的鸭子就去实现flyable接口,会叫的鸭子实现Quackable接口。

领导看见了jack的这种设计模式,还是一脸不高兴,虽然你用接口的方法去解决所有鸭子继承的缺陷,但是使用接口的话,却造成代码无法复用,这只能是从一个噩梦跳进另一个噩梦,甚至,在会飞的鸭子中,飞行的动作也是千变万化。

如果能有一种建立软件的方法,好让我们可以用一种对既有的代码影响最小的方式来修改软件该有多好,我们就可以花较少的时间重做代码,而多让程序做更酷的事情。

现在我们知道使用继承不能很好的解决问题,因为鸭子的行为在子类里不断改变,并且让所有鸭子都有这些行为是不恰当的。使用接口也是有问题的,因为在接口中,并没有代码的实现,会造成代码不能复用,在每个实现的子类都要实现该方法,不可取。

设计原则一

找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

好了,该是把鸭子的行为从duck类中取出的时候了!

现在,为了要分开“变化和不会变化的部分”,我们准备建立两组类,一个是fly相关的,一个是quack相关的,每一组类都将实现各自动作,比方说,我们可能有一个类实现“呱呱叫”,另一个类实现“吱吱叫”,还有一个类实现“安静”。

设计原则二

针对接口编程,而不是针对实现编程

为了不让鸭子子类直接实现行为接口,我们设计了一个行为接口类FlyBehavior和QuackBehavior 所表示的行为,所以实际的“实现”不会被绑死在鸭子的子类中。看类图

接下来,有了以上的行为类,我们只要把这些行为类作为鸭子类的属性,注入就行。

我们实现代码

/*** Created by huangx on 2018/11/12.*/
public interface Flybehavior {public void fly();
}
/*** Created by huangx on 2018/11/12.*/
public class FlyWithWings implements Flybehavior{public void fly() {System.out.println("i am flying!");}
}
/*** Created by huangx on 2018/11/12.*/
public class FlyNoWay implements Flybehavior{public void fly() {System.out.println("i cant fly");}
}
/*** Created by huangx on 2018/11/12.*/
public interface QuackBehavior {public void quack();
}
/*** Created by huangx on 2018/11/12.*/
public class Quack implements QuackBehavior {public void quack() {System.out.println("quack");}
}
/*** Created by huangx on 2018/11/12.*/
public class MuteQuack implements QuackBehavior{public void quack() {System.out.println("silence");}
}
/*** Created by huangx on 2018/11/12.*/
public abstract class Duck {Flybehavior flybehavior;QuackBehavior quackBehavior;public Duck(){}public abstract void display();public void performFly() {flybehavior.fly();}public void performQuack(){quackBehavior.quack();}public void swim(){System.out.println("All duck can float");}
}
/*** Created by huangx on 2018/11/12.*/
public class MallardDuck extends Duck {
// 属性不仅能通过构造函数注入,也可以通过set方法注入,看你心情。public MallardDuck(){super.flybehavior=new FlyWithWings();  //这是可飞的鸭子 给他设置会飞的属性super.quackBehavior=new Quack();  //这是能叫唤的鸭子 给他设置会叫的属性}public void display(){System.out.println("i am  a real Mallard duck");}
}
/*** Created by huangx on 2018/11/12.*/
public class TestDuck {public static void main(String[] args) {Duck mallard=new MallardDuck();mallard.performFly();mallard.performQuack();}
}

领导看见jack的这个设计,高兴坏了,立马打电话让财务给jack加工资,并为她介绍女朋友!

这就是策略模式,策略模式的官方定义是他封装了算法族,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

结束了,这是我的第一篇技术blog,还希望以后我能继续坚持写下去!!!

我的武林秘籍设计模式之策略模式相关推荐

  1. 我的武林秘籍设计模式之命令模式

    今天我们讲命令模式,首先我们先从一个故事开始. NBA2018-2019赛季,季后赛正如火如荼的进行中,今天来到的比赛正是西部总决赛休斯顿火箭队与金州勇士队的天王山之战. 这边火箭主帅德安东尼所派出的 ...

  2. Java设计模式之策略模式与状态模式

    一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. 好了,定义看看就完了,我知道你很烦看定义. 二.策 ...

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

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

  4. 研磨设计模式之 策略模式--转

    http://www.uml.org.cn/sjms/201009092.asp 研磨设计模式之 策略模式   2010-09-09 作者:云飞龙行 来源:云飞龙行的blog   先感谢众多朋友的支持 ...

  5. 设计模式:策略模式(Strategy)

    定   义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...

  6. C++设计模式之策略模式(Strategy)

    Strategy策略模式 作用:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. UML图: 代码实现 #include <iostream& ...

  7. python策略模式包含角色_详解Python设计模式之策略模式

    虽然设计模式与语言无关,但这并不意味着每一个模式都能在每一门语言中使用.<设计模式:可复用面向对象软件的基础>一书中有 23 个模式,其中有 16 个在动态语言中"不见了,或者简 ...

  8. 一篇博客读懂设计模式之-----策略模式

    设计模式之策略模式 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的对象 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换. 主要解决:在有多种算法相似的情况下 ...

  9. 面向对象设计模式之策略模式

    面向对象设计模式之策略模式 1.策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户 2.抽象鸭子类,鸭子飞行行为在此处类似于算法族 1 package ...

最新文章

  1. poj 2891 Strange Way to Express Integers 2012-09-05
  2. 成功解决ValueError: Found input variables with inconsistent numbers of samples: [86, 891]
  3. javascript事件之:jQuery事件中实例对象和拓展对象之间的通信
  4. puppeteer( Nodejs 版 selenium )快速入门
  5. Express框架的安装通信测试 - 讲解篇
  6. 领会CSS,实际中的研究
  7. MySQL高级-视图
  8. 「一入 Java 深似海 」系列课程
  9. Android Studio 如何修改项目名称
  10. 这才是 Python 的 “72 变”玩法!
  11. ubuntu下Chrome浏览器字体问题 字体发虚解决办法
  12. Visual Entity 使用(四)添加、删除属性
  13. 海尔计算机显卡驱动,海尔t621显卡驱动(最新更新)海尔t68d显卡驱动
  14. USGS下载LANDSAT5 2级别 影像问题
  15. pycharm远程操作linux进行开发
  16. 实现财务自由的关键词汇
  17. “网络吸血鬼” Leech
  18. 收藏!转型AI工程师必读
  19. JS学习之BOM | 常见网页特效 | 轮播图 | 返回顶部 | 筋斗云案例
  20. 【uni-app学习】uni-app低功耗蓝牙采坑记录

热门文章

  1. 【python】B站电影爬虫
  2. Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】
  3. 流畅的Python阅读笔记(二)
  4. docker端口映射或启动容器时报错Error response from daemon: Container is not running
  5. HiBench算法简介
  6. Sysweld笔记:利用稳态算法加速算法模拟焊接过程的残余应力
  7. SAS/SATA/SSD/IDE硬盘介绍区别
  8. 警惕安全档案的陷阱 | 确认偏见
  9. Markdown 公式编号及引用
  10. 丰巢科技-Java高级