近日阅读著名的《Head First 设计模式》,深深被作者生动风趣的讲解风格打动。作者让看似高深的设计模式变得像游戏一样好玩,这也是一种非常高效的传授知识的方式。介于对作者所讲的每一章都感觉回味无穷,心里有种冲动将回味转化为白纸黑字,供自己回味同时,也希望起到抛砖引玉之用~~~(原书作者不要投诉我。。)
今天首个要回味的是策略模式,先不管这个名字,咱先讲故事~~
你是某游戏公司的软件工程师Joe,现在有个打鸭子的游戏要做,因为鸭子种类很多(假如确实非常多,包括假的鸭子),你这样定义鸭子类:
当你做好了这些类以后,产品经理有一天对你说,现在要为每种鸭子添加飞的功能。你觉得作为一个OO软件开发的人来说太easy了,于是你用继承在Duck添加了fly方法如下:
正当你为自己的速度感到相当有成就感的时候,产品经理黑着脸过来,“为什么橡皮鸭子也会飞啊!”。。
原因很简单,所有的类都继承Duck的fly方法嘛~~使用继承的方式会牵一发而动全身,使得不该用这种方法的鸭子也被强制添加上了这种方法。
但聪明的你很快想到了面向对象的方法覆盖,把不会飞的鸭子的fly方法覆盖为空不就得了。
但是产品经理又一次黑着脸。。“如果以后添加很多鸭子,有些不会飞,有些不会叫,有些都不会,你倒一个个给我改试试看!?”。。。
这时你意识到,需要一个更清晰的方法让鸭子指定可以飞或者可以叫。
不是有接口么?让会飞的实现飞的接口,会叫的实现叫的接口不就行了?
这时黑着脸的产品经理再次出现。。“你这样重复代码不得很多么?!以后要改某些鸭子的飞行行为不是得一个个改?!”。。
此时你意识到如果能有一种建立软件的方法,好让我们可以用一种对既有的代码影响最小的方式来修改软件该有多好。我们就可以花较少时间重做代码,而多让程序去做更酷的事……这个世界那该美好许多啊。
于是你去深山中拜访大师,大师就吐了一句话:“找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。”。。
大师一语惊醒梦中人,于是你很快想到:为了要分开“变化和不会变化的部分”,我们准备建立两组类(完全远离Duck类),一个是“fly”相关的,一个是“quack”相关的,每一组类将实现各自的动作。比方说,我们可能有一个类实现“呱呱叫”,另一个类实现“吱吱叫”,还有一个类实现“安静”。我们知道Duck类内的fly()和quack()会随着鸭子的不同而改变。为了要把这两个行为从Duck类中分开,我们将把它们从Duck类中取出来,建立一组新类来代表每个行为。
那如何设计那组实现飞行和呱呱叫的行为的类呢?你想不懂,于是打了个电话给山林中的大师,深沉的大师又只说了一句:“针对接口编程,而不是针对实现编程。“。。
你果然聪明人,一点就破,立刻想出如下方法:
从现在开始,鸭子的行为将被放在分开的类中,此类专门提供某行为接口的实现。
这样,鸭子类就不再需要知道行为的实现细节。在新设计中,鸭子的子类将使用接口(FlyBehavior与QuackBehavior)所表示的行为,所以实际的“实现”不会被绑死在鸭子的子类中。像这样: