第一节的内容,不知道大家看的如何。小编在博客园的评论里,找到了第一篇的一个缺点,没有把动态改变行为的Duck子类列出来,导致有小伙伴有疑问。在这里说声抱歉,是我疏忽了,好在有GitHub,让大家可以进去一窥究竟,在后续的学习中我也会注意此类问题。
先来解答下上次课程留下的思考题,利用继承来提供Duck的行为,这会导致哪些缺点。有以下几个(看看你的答案是否和他吻合呢):
√A 代码再多个子类中重复
√B 运行时的行为不容易改变
√D 难以得知所有鸭子的全部行为
√F 改变会牵一发动全身,造成其他鸭子不想要的改变
然后我们再来回顾下,上一篇说到的几个变化,通过类图再次给大家做下复盘。首先来看下最初是的简单的模型,此时鸭子只会呱呱叫、有外观显示以及游泳的能力。
接下来,我们想让鸭子飞,一开始用了继承的方式来解决,导致不需要飞行的鸭子类也继承了这功能, 显然是不太合理的,也就是开篇说到的继承存在的几个缺点。
哈哈,所以我们需要通过接口来实现,把飞行和呱呱叫功能封装成接口,只有需要相应能力的鸭子自行去实现此接口,这样就能达到按需获取的情况
上图中的Flyable和Quackable 就是鸭子类需要各自去实现的功能,按需实现。那我不想飞的鸭子就不用飞了,不想叫的鸭子就不需要叫了,让他静静地待着吧。
在上图我们看到了两个接口是五个实现类,很明确吧,把飞行,不飞行, 呱呱叫,吱吱叫,不叫给你分的清清楚楚,明明白白。
接下来,就是整合鸭子的行为,也就是我在代码里没写明白的部分,实在是对不起各位。
在Duck子类创建的时候,先在构造器里默认创建各个行为类,比如你需要呱呱叫,并且是飞行的行为。
这就是默认的行为,然后你需要动态改变行为,就如前文所说,用setter方法重新定义你需要创建的行为即可,你创建的鸭子能从不会飞变身成装上火箭助推器的鸭子般给力
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I'm flying with a rocket!");
}
}
Duck model = new ModelDuck();
// 第一次调用,不会飞
model.performFly();
// 调用继承来的setter方法,把火箭动力飞行的行为定到模型鸭中,模型鸭能一飞冲天
model.setFlyBehavior(new FlyRocketPowered());
// 这样就成功的改变了行为
model.performFly();
整个过程最后的图就是一个父类的Duck,若干个Duck的子类,一个飞行行为的接口,一个呱呱叫的接口以及若干个针对接口的实现
好啦,这样又和大家一起回顾了一遍上一篇的整体流程,你消化了吗。
在此,我还想聊聊为什么我们需要设计模式。书中也有提到,大致的意思就是,一个程序员在描述一个功能的时候,巴拉巴拉讲了一堆,说要建立一个广播类来跟踪所有的对象,只要有更新,就会通知每个倾听者。这些倾听者可以随时加入广播系统,也可以随时移除 。结果,一个拥有设计模式的老鸟就随口说了一句,你用「观察者模式」来描述刚才的这个场景,简单方便,易于沟通,还把所有需要的功能都清楚了,大家相视一笑,哈哈。忽然发现,我有时候也会对我熟悉的设计模式脱口而出,尤其是这个观察者模式,原来有些东西已经在无形之中影响了我,影响着你。
在书中,这个场景叫「共享模式」。共享模式词汇威力如下:
-
当你使用模式名称和其他开发人员或者开发团队沟通时,你们之间交流的不只是模式名称,而是一整套模式背后所象征的质量、特性、约束。
-
模式能够让你用更少的词汇做更充分的沟通。
-
当你用模式描述的时候,其他开发人员便很容易地知道你对设计的想法。
-
将说话的方式保持在模式层次,可以让你待在「设计圈子」久一点。
-
使用模式谈论软件系统,可以让你保持在设计层次,不会被压低到对象与类这种琐碎的事情上面。
-
对于设计模式有深入理解的团队,彼此之间对于设计的看法不容易产生误解。
现在我们对设计模式有了一个初步的认识,接下去就要开始进入这个美妙的世界了。但是,先别急,我们需要带上属于我们的工具,把设计模式一一修理干净。其实你应该已经猜到是什么了吧。我还是再啰嗦一下
- OO基础
抽象、封装、继承、多态
- OO原则
封装变化
多用组合,少用继承
针对接口编程,不针对实现编程
- OO模式
『策略』--定义算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
走进设计模式的世界部分就给大家介绍到这里,拿起我们的工具,往前进吧。
PS:因为最近几天项目忙,GayHub的事情稍微有点延迟,周末我好好整理下,会尽快输出。