将行为(算法)封装起来,让它们之间可以互相替换,此模式让行为的变化独立于使用行为的客户。
很久之前,老板喊我过去开发一款游戏,说日后必火,于是我日夜Coding,终于搭建好了项目框架。秉着OO设计原则,我定义了一个召唤师基类(Summoner),然后继承下来两个召唤师:Firegirl和Galen。
由于所有召唤师都具有相同个数的技能,并且能够走路,因此我在基类中将fetchSkillCounts、walk方法实现,这样便达到了代码复用的效果;但是每一个召唤师的外观都不一样,因此我将display设计成了抽象方法,并在Firegirl与Galen中做了各自的实现。
就这样,我很轻松的又开发出了Ashe、Rizi等召唤师。
然而好景不长。过了几天,老板说要开发一个叫Kell的召唤师,他虽然有两只脚,但是被绑在了一起,所以不能走路,但是他长了一双天使般的翅膀,因此他可以飞,飞,飞。
这并不能难倒我,不就是要飞么,爬我都能给你做出来。于是乎,我在Summoner中增加了一个fly方法。
但是越来越多的召唤师,把我压的喘不过气来。因为每增加一个召唤师,我都要根据他是否可以走路或者飞行,选择性的覆盖fly或者walk方法,这不仅导致子类中存在大量重复的代码,而且在基类中增加方法,会牵一发动全身,造成其他子类不想要的改变。想想以后如果真要有爬的,我还要覆盖更多的方法,简直就是噩梦。
不得已,我使用接口(协议)重新进行了设计。
将步行与飞行动作从基类中抽离了出来,定义成了接口,这样某个召唤师需要步行动作时就可以实现WalkInterface接口,需要飞行动作时就实现FlyInterface接口,看似解决了继承带来的负面影响,但也失去了通过继承达到代码复用的效果,因为我必须在每个召唤师里根据需要去实现walk或者fly方法。
只能接着完善设计,路漫漫其修远兮。。。
终于,功夫不负有心人。
[相关的完整代码(iOS)](https://github.com/liangjie-MrJie/DesignPattern)
这样的设计,使得步行和飞行动作与召唤师类无关了,可以让它们更容易的被其他对象复用,而且当新增一些其他动作时,不会影响到已有的动作类。
如果老板希望在游戏中当某个事件触发后,改变召唤师的行为动作,通过以上的设计,完全可以动态更改召唤师的动作,so easy!
使用策略模式将召唤师的行为动作封装成了算法簇,并且可以让召唤师动态的改变自己的算法,呈现出不同的形态。这样的代码设计,可以为以后的维护节省大量时间。
倾情告白:多用组合,少用继承,“有一个”要比“是一个”更好!
关注微信公众号CodingArtist,可以第一时间得到文章更新通知! _
网友评论