HeadFirst学习笔记-1. 设计模式入门
1.概念
在开始学习前,我们先了解一些概念,方便我们接下来的学习。
OO基础
抽象
继承
多态
封装
OO原则
封装变化
多用组合,少用继承
针对接口编程,不针对实现编程
设计模式
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 -- 来自百度百科
2.案例
我们从一个案例项目开始我们的学习之旅。
项目背景
Joe上班的公司做了一套相当成功的模拟鸭子游戏:SimUDuck。游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。此系统的内部设计使用了标准的OO技术,设计一个鸭子超类,并让各种鸭子继承此超类。
根据项目需求,设计项目结构,如下图:

新需求
现在我们得让鸭子能飞,怎么办?
最直接的办法就是在超类里添加Fly行为,因此Joe在Duck类里增加了Fly行为。如下图:

出问题了
但是,可怕的问题发生了...游戏里出现了很多会飞的“橡皮鸭”,这与现实不符。为什么会出现这个问题?
原来Joe忽略了一件事情:并非所有的Duck子类都会飞。Joe在Duck父类中加上新的行为,会使得某些并适合该行为的子类也具有该行为。
注:不要轻易在父类中添加行为或属性。

使用继承?
Joe想到了继承,把橡皮鸭类中的Fly行为覆盖掉。如果以后增加木头鸭(WoodDuck),又会怎样呢?木头鸭不会叫,又不会飞。。。
使用继承的话,很容易出现需要对大量的子类进行修改。
使用接口?
Joe把Fly()从父类中取出来,定义一个“Flyable”接口,只有会飞的鸭子才实现此接口,同样的,也设计一个“Quackable"接口,因此也不是所有鸭子会叫。如下图:
这样一来,重复的代码更多了,假如你要修改48个Duck子类的Fly()行为,会崩溃的。如果你是Joe,你会怎么办?

不变的是变化
面对上面的问题,有一个设计原则适用于此状况:
封装变化:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
分开变化和不会变化的部分
从哪里开始呢?就我们目前所知,除了Fly()和Quack()的问题之外,Duck类还算一切正常,为了要分开“变化和不会变化的部分”,我们准备建立两组类(完全远离Duck类),一个是“Fly”相关的,一个是“Quack”相关的,每一组类将实现各自的动作。

设计鸭子的行为
如何设计那组实现Fly和Quack的行为的类呢?
我们希望一切能有弹性,毕竟,正是因为一开始鸭子行为没有弹性,才让我们走上现在这条路。还想能够“指定”行为到鸭子的实例。
为了满足以上目标,第二个设计原则适用于此状况:
针对接口编程,而不是针对实现编程。
我们利用接口代表每个行为,比方说,FlyBehavior与QuackBehavior,而行为的每个实现都将实现其中的一个接口。

实现鸭子的行为
在此,我们有两个接口,FlyBehavior和QuackBehavior,还有它们对应的类,负责实现具体的行为:

这样的设计,可以让Fly和Quack的动作被其他的对象复用,因为这些行为已经与鸭子类无关了。
而我们可以新增一些行为,不会影响到既有的行为类,也不会影响“使用”到Fly行为的鸭子类。
整合鸭子的行为
关键在于,鸭子现在会将飞行和呱呱叫的动作“委托”(delegate)别人自理,而不是使用定义在Duck类(或子类)内的呱呱叫和飞行方法。
1、首先,在Duck类中“加入两个实例变量”,分别为“flyBehavior”和“quackBehavior”。
2、实现performFly()和performQuack()
3、初始化实例变量“flyBehavior”和“quackBehavior”。

“有一个”可能比“是一个”更好
这是一个很重要的技巧。其实是使用了我们的第三个设计原则:
多用组合,少用继承。
动态设置行为
通过setter来设定鸭子的行为,而不是在构造器内实例化。
public void SetFlyBehavior(flyBehaivor fb){
flyBehaivor = fb;
}
public void SetQuackBehavior(flyBehaivor qb){
quackBehaivor = qb;
}
整体结构

3.总结
案例中使用了第一个设计模式:策略模式(Strategy Pattern)
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
策略模式结构图:

HeadFirst学习笔记-1. 设计模式入门的更多相关文章
- Hadoop学习笔记(1) ——菜鸟入门
Hadoop学习笔记(1) ——菜鸟入门 Hadoop是什么?先问一下百度吧: [百度百科]一个分布式系统基础架构,由Apache基金会所开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序. ...
- iOS学习笔记-地图MapKit入门
代码地址如下:http://www.demodashi.com/demo/11682.html 这篇文章还是翻译自raywenderlich,用Objective-C改写了代码.没有逐字翻译,如有错漏 ...
- tensorflow学习笔记二:入门基础 好教程 可用
http://www.cnblogs.com/denny402/p/5852083.html tensorflow学习笔记二:入门基础 TensorFlow用张量这种数据结构来表示所有的数据.用一 ...
- spark学习笔记总结-spark入门资料精化
Spark学习笔记 Spark简介 spark 可以很容易和yarn结合,直接调用HDFS.Hbase上面的数据,和hadoop结合.配置很容易. spark发展迅猛,框架比hadoop更加灵活实用. ...
- 我的设计模式学习笔记------>Java设计模式总概况
设计模式(Design Pattern)的概念最早起源于建筑设计大师Alexander的<建筑的永恒方法>一书,尽管Alexander的著作是针对建筑领域的,但是他的观点实际上用用于所有的 ...
- MyBatis学习笔记(一)入门
首先给大家推荐几个网页: http://blog.csdn.net/isea533/article/category/2092001 没事看看 - MyBatis工具:www.mybatis.t ...
- 【NodeJS 学习笔记02】入门资源很重要
前言 在我映像中,异步最早出现与ajax,当时我还在搞.net,然后.net居然出了一个异步的控件...... 虽然我最后知道了他不是异步的......然后,前端异步用得特别多,如果不是异步的程序,你 ...
- [置顶] 我的设计模式学习笔记------>Java设计模式总概况
设计模式的概念最早起源于建筑设计大师Alexander的<建筑的永恒方法>一书,尽管Alexander的著作是针对建筑领域的,但是他的观点实际上用用于所有的工程设计领域,其中也包括软件设计 ...
- SQL学习笔记——SQL初入门,Ubuntu下MySQL的安装
刚开始接触sql,于是准备在Ubuntu下学习sql,就跟着itercast的sql教程开始入门了. 下面只是我个人的记录,高手请绕道: 一. 在安装之前,我们可以用下面这个命令通过开放端 ...
随机推荐
- 【洛谷P1402】酒店之王
题目大意:有三个集合 \(P,Q,N\),P 与 N 集合之间存在一些有向边,N 与 Q 集合之间存在一些有向边.在三个集合中每个点最多只能利用一次的前提下,求最多能利用多少N 集合中的点,使得 \( ...
- 老男孩Python全栈学习 S9 日常作业 011
1.编写装饰器,为函数加上统计时间的功能 import time def Decoration(func): def Timmer(): # 开始时间 Start = time.time() func ...
- JS基础-第5天
复习函数 函数 作用:封装一段代码,封装的功能可以被反复调用执行. 定义函数 // 第一种 - 函数声明 function 函数名(){ } // 第二种 - 函数表达式 var 函数名 = func ...
- 网络协议 HTTP入门学习
概述 Web 的诞生,源于三大技术的诞生,它们都是当年 Web 之父 Tim Berners-Lee 自己 开发的,世界上第一个网站诞生的时间是 1991 年,三大技术的诞生也就是在此之前的不久: 1 ...
- [Reinforcement Learning] 强化学习介绍
随着AlphaGo和AlphaZero的出现,强化学习相关算法在这几年引起了学术界和工业界的重视.最近也翻了很多强化学习的资料,有时间了还是得自己动脑筋整理一下. 强化学习定义 先借用维基百科上对强化 ...
- python常用的内置函数
python常用的内置函数集合做一个归类用的时候可以查找- abs 返回数字x的绝对值或者x的摸 - all (iterable)对于可迭代的对象iterable中所有元素x都有bool(x)为tru ...
- docker学习------swarm集群虚机异常关机,node状态为down
1.因昨天虚机异常关闭,导致今天上去查看时,node节点状态显示为down 2.查了些相关资料,找到处理办法(因我的节点没有任何数据,所以直接对其进行清除) docker swarm leave -- ...
- opencv中imgshow图像显示为灰色
1.图像数据类型是否正确 2.图像是否存在 3.在imgshow()语句下添加watkey();
- 20164305 徐广皓 Exp1+ 逆向进阶
实验内容 Task1 (5-10分) 自己编写一个64位shellcode.参考shellcode指导. 自己编写一个有漏洞的64位C程序,功能类似我们实验1中的样例pwn1.使用自己编写的shell ...
- EL表达式 - 日常使用表达式记录
表达式 说明 ${field} 查找域,page ->request -> session -> application 中的值. ${field == null ? field1: ...