Ps:类似原文。
有一款游戏,内容是鸭子的生活,你可以扮演一只鸭子,游泳、呱呱叫还可以鸭子式的起飞。游戏内部设计里,有一个祖类(Superclass),囊括了鸭子的基本生活行为,不同的鸭子种类只需要继承再重写abstract方法,就可以衍生出唐老鸭、周黑鸭之类拥有自己特色的鸭子,UML建模如下:
游戏很受欢迎(强行受欢迎),于是要进行下一版本的开发,要添加让鸭子飞行的功能!!!这有啥难的,在祖类(Superclass)中添加一个fly方法,所有通过继承派生出来的鸭子不就能飞了么,于是bulabula,新的模型出来了,如下所示:
这时候,就会有小伙伴发现一个大问题了,唐老鸭飞起来也就算了,可是你周黑鸭飞起来了算啥,输了的鸭子飞了么…于是乎,这第二版游戏需要回炉重造。这时候,在重新设计的时候,我们就考虑到了程序的拓展性问题(Ps:正确性、健壮性、可靠性、效率、易用性、可读性(可理解性)、可扩展性、可复用性、兼容性)。
解决周黑鸭也飞起来的问题,最快速的解决办法是在周黑鸭类中通过覆盖父类方法使得周黑鸭能飞的bug消失了!然而,游戏非常受欢迎(强行非常),后续肯定会添加更多的鸭子种类,如果使用覆盖,那么每有一个新的类别的鸭子加入游戏,那么就要对fly方法判断是否需要覆盖。有的小伙伴可能就说了,鸭子能有多少种,这么判断工作量也不会太大的,然后too young too simple,鸭科鸟类在物种分类学上一般分为10个亚科:有44属156种。
更何况还有各种存在于二次元的鸭子?这样还只是fly的覆盖呢,不同的鸭子叫声也不同,唐老鸭能说人话,周黑鸭…周黑鸭心想:“我想静静,别问我静静是谁”。当大量的对象出现,覆盖就会使工作量大量重复,那么此时,我们考虑一下,如果我们使用接口会如何?将飞行fly和鸭子叫quack抽离出来,做成接口,每个鸭子只要实现这俩接口就可以设置属于自己类别的飞行模式和鸣叫特色了,然而,工作量似乎并没有减少多少呀,甚至代码量还变得更多了,如果代码能够复用就好了。
那么,如果制造出专门实现fly接口的类和quack接口的类,组成行为类如何呢?简单模型如下:
那么,在众多的鸭子中,用翅膀飞的鸭子只需要使用FlyWithWings即可实现自己的飞行方式,也不用在每个鸭子类中重复编写飞行方式代码,但是如何使用FlyWithWings这个类呢?唐老鸭、周黑鸭等鸭子们已经继承过Duck了,根据语法规则,不能再继承FlyWithWings了。那么,我们在Duck中,定义两个实例变量如何?如下所示:
那么问题来了?如何让行为生效呢?我们在Duck类中再添加两个与第二个模型中的quack和fly方法类似的行为方法performFly和performQuack即可。模型修改如下:
粗略代码如下:
现在!我们来创建一个周黑鸭类出来,代码如下:
MuteQuack的代码如下:
那么,现在只需要进行测试就可以看到最后成果了:
结尾注:
其实大部分内容属于搬运,原创很少,而且还删除了原书的部分内容,以后会慢慢的更多实用自己的理解去阐述一个模式,第一次试水,代码不全还需要小伙伴们自己去写,千万不要百度,代码这东西,虽然是已经造出来的车轮子,但是自己造一边,会理解的更好。
最后的最后,Head First设计模式这本书不错,强行安利。
设计模式-学习随笔(一)
最新推荐文章于 2021-03-16 09:50:08 发布