《Head First》 设计模式之一 Strategy model

zhi hu 上讲到开发人员推荐看的好书,有一套head first 系列很受推荐,正好最近也在看设计模式方面的书,所以就先在网上找了pdf文档,也准备写一个系列的博客记录学习的过程,this is the first blog 。
Head first 设计模式第一个讲到的模式就是 ---策略模式---
策略模式的定义(对客户,对领导,对同事的装逼说法):定义了算法族,分别封装起来,让他们之间可以相互替代,此模式使算法的变化独立于使用算法的用户 。
关于设计模式,我们通常理解为,解决一类问题的指导方法,是之前遇到此问题的程序员,架构师总结出来的一套行之有效,灵活的,可扩展的经验 。我们学习了设计模式,就可以在遇到问题的时候,不必自己再重新制造轮子 。那我们学习设计模式的时候也要时刻注意每种设计模式对应的问题 。之所以书名叫head first ,就是要让我们多思考,多理解,融汇贯通 。
那策略模式是为了解决什么问题的呢 。是为了解决由于继承导致的耦合,在学习uml的时候,我们知道继承是耦合最强的一种模式,远不如实现接口和组合 。所以策略模式解决的就是把继承改为组合(此处的组合只has-a,继承指is-a) 。

《Head First》 设计模式之一 Strategy model

文章插图
书中给的例子是一个游戏,游戏中有各种各样的鸭子(Duck),鸭子可以叫,游泳 。一开始我们顶一个父类Duck,然后继承Duck之后有了很多野鸭,木头鸭,橡胶鸭,可达鸭,大黄鸭 。一切都很完美,但是有一天产品经理设计的新版本,让鸭子可以飞起来,这个时候如果在父类中直接添加fly方法,那大黄鸭和可达鸭是不会飞的 。如果单独在子类中添加此方法,代码影响也非常大,所以这个时候我们明白这个fly能力其实不应该算是Duck的属性,那么基于一种能力的设计思想,fly要被定义为接口,关键是在Duck中定义fly属性 。而不是在Duck或者子类中直接实现接口 。这个地方的设计思想是:把经常变动的和不变的区分开,把经常变动的抽象封装起来,就可以在运行的时候动态更改实现,
《Head First》 设计模式之一 Strategy model

文章插图
【《Head First》 设计模式之一 Strategy model】例如
public abstract class Duck {private FlyBehavior flyBehavior;private QuackBehavior quackBehavior;public abstract void display();}
《Head First》 设计模式之一 Strategy model

文章插图
public interface FlyBehavior {void fly();}
public interface QuackBehavior {void quak();}
这样我们就能在运行的时候动态决定Duck怎么飞行,怎么叫 。
可能大家有疑惑,这样做其实跟直接修改每个子类的复杂度差不多,但是我们看到书名是Head first,所以我们在设计程序之前就应该多思考,我们未来会遇到什么养的问题,甚至是养成一种好的习惯,习惯使用has-a而不是is-a 。
下面我们思考书中提出的另一个问题,设计一款游戏,游戏角色包括射手,坦克,辅助,法师,刺客 。而随着角色的等级发展,角色可以扩展自己的技能 。当我们在设计这么一款类似农药的时候,我们会怎么设计呢?