单一原则:将一个责任只指派给一个类。
如果一个类具有两个改变的原因,那么这会使得将来该类的变化机率上升,而当它真的改变时,你的设计中同时有两个方面将会受到影响。
难道在于如何区分不同的责任
做法:努力不懈地检查你的设计,随着系统的成长,随时观察有没有迹象显示某个类改变的原因超出一个。
内聚:它用来度量一个类或者模块紧密地达到单一目的或责任。
当一个模块或一个类被设计支持一组相关的功能时,我们说它具有高内聚;反之,当被设计成支持一组不相关的功能时,我们说它具有低内聚。
低内聚不容易维护。
组合模式
组合模式以单一责任设计原则换取透明性,什么是透明性?通过让组件的接口同时包含一些管理子节点和叶子节点的操作,客户就可以将菜单和菜单项一视同仁。
我们在接口中同时具有两种类型的操作。因为客户有机会对一个元素做一些不恰当或者是没有意义的操作(例如试图把菜单添加到菜单项)。所以我们失去了一些“安全性“。这是设计上的抉择;我们也可以采用另一种方向的设计,将责任区分开来放在不同的接口中。这么一来,设计上是比较安全,但我们也因此失去了透明性,客户的代码将必须用条件语句和instanceof操作符处理不同类型的节点。
所以书中的例子是一个很典型的折衷案例。这个模式更强调统一处理,避免更多的条件或者类型判断。
NullIterator的hasNext永远为false,这是一个技巧。
模式告白:
组合模式:
当你有数个对象的集合,它们彼此之间有“整体/部分“的关系,并且你想用一致的方式对待这些对象时可以采用组合模式。
“整体和部分“:画板中的依赖关系是不是也可以转成树型结构,来模仿组合模式,然后统一的Draw呢。
有时候,组合结构很复杂,或者遍历代价太高,比方说,你要不断地遍历一颗树,而且它的每个子节点都需要进行某些计算,你就可以使用缓存来临时保存结果。
主要优点:不需要操心面对的是组合对象还是叶子节点对象,所以就不需要写一大堆的if语句来保证他们对正确的对象调用了正确的方法。通常,只需要对整个结构调用一个方法并执行操作就可以!
模式连连看
客户可以将对象的集合或者个别对象一视同仁--------组合模式
提供一个方式来遍历集合而无须暴露集合的实现------迭代模式
简体一群类的接口-----外观
改变一个或者多个类的接口-----适配器
当某个状态改变时,允许一群对象能被通知------观察者
封装可互换的行为,并使用委托决定使用哪一个-----策略模式
状态模式:
基本常识:策略模式和状态模式是双胞胎,在出生时才分开。
思路:改变对象内部状态来帮助对象控制自己的行为,它常常告诉它的对象客户:“跟着我念:我很棒,我很聪明,我最优秀了“。
我想它是想强调这个模式是自己影响自己的行为
需要一个状态图
状态模式,有可能会被用到元件的管理上,因为它有很多状态
优点:
1将每个状态的行为局部化到它自己的类中
2将容易产生问题的if语句删除,方便日后维护
3让每一个状态对“修改关闭“,让糖果机对”扩展开发“,因为可以加入新的状态类。
状态模式解释:
将状态封装成独立的类,并将动作委托到代表当前状态的对象,当前状态对象执行的动作,好像改变了原对象的行为。这是一种假象。
例如:糖果机的接口动作有:投钱,退钱,糖果售完,售出糖果。其实这些动作都是糖果机的,但是却在状态中执行。正常的逻辑是这个接口应该由糖果机来实现,但确由状态来实现。
用模式的眼睛去看MVC:
1视图和控制器之间实现了经典的策略模式:
视图是一个对象,可以被调整使用不同的的策略,而控制器提供了策略。视图只关心系统中可视的部分,对于任何界面行为,都委托给控制器处理。
使用策略模式可以让视图和模式之间的关系解耦,因为控制器负责和模型交互来传递用户的请求。对于工作是怎么完成的,视图毫不知情。如果你希望有不同的行为,可以直接换一个控制器。
2视图内部使用组合模式来管理窗口,按钮以及其他显示组件。
显示包括了窗口、面板、按钮、文本标签等。每个显示组件如果不是组合节点(例如窗口),就是叶子节点(例如按钮)。当控制器告诉视图更新时,只需要告诉视图最顶层的组件即可,组合会处理其余的事。
这里,视图这里用组合,也许会适于我的画板程序,但很明显视图的模式要求组件的关系是一个树型的关系,是一种包含关系,而我要做的画板中,每个元件的关系是平等,但函数部分也这种父子关系,这里要仔细考虑一下。
3模型实现了观察者模式,当状态改变时,相关对象将持续更新。使用观察者模式,可以让模型完全独立于视图和控制器。同一个模型可以使用不同的视图,甚至可以同时使用多个视图。
与设计模式相处
1情境
2问题
3解决方案
4情境和问题重复出现,解决方案也可以重复使用!
5 解决方案更抽象,而且通用!
学习和快速定位到自己需要的模式的方法:
1模式分类
2模式名
3意图:简短的描述该模式的作用。你也可以把它看作是模式的定义。
4动机:给出问题以及如何解决问题的场景。
5适用性:描述模式可以被应用的场合。
6结构:显示出参与此模式的类之间的关系。
7参与者:描述在此设计中所涉及到的类和对象在此模式中的责任和角色。
8协作:告诉我们参与者如何在此模式中合作。
9结果:描述采用此模式之后可能产生的效果:好的与不好的。
10范例代码:提供代码的片段,可能对你的实现有所帮助。
11实现:提供了你在实现该模式时需要使用的技巧,以及你应该小心面对的问题。
12已经应用:用来描述已经在真实系统中发现的模式例子。
13相关模式:描述了此模式和其他模式之间的关系。
设计模式的学习:
1对现有模式的熟练掌握
2多思考
3将你的想法记录下来
4多与人讨论,并应用到实际中验证
常用模式与描述
1策略:封装可以互换的行为,并使用委托来决定要使用哪一个
2观察者:让对象能够在改变时被通知。
3装饰者:包装一个对象,以提供新的行为。
4工厂方法:由子类决定要创建的具体类是哪一个。
5抽象工厂:允许客户创建对象的家族,而无需指定他们的具体类。
6单件:确保有且只有一个对象被创建。
7命令:封闭请求成为对象。
8适配器:封装对象,并提供不同的接口。
9外观:简化一群类的接口。
10模板方法:由子类决定如何实现一个算法的步骤。
11迭代:在对象的集合之中游走,而不是暴露集合的实现。
12组合:客户用一致的方式处理对象集合和单个对象。
13状态:封装了基于状态的行为,并使用委托在行为之间切换。
14代理:包装对象,以控制对此对象的访问。
15复合(MVC)
模式分类:
模式分类是为了更好的理解模式。
你会发现有的模式似乎同时属于不同的类目,其实怎么分类不重要,重要的是了解这些模式和它们之间的关系。只要类目有帮助就用它,反之就不用。
第一种分类
1创建型
涉及到将对象实例化,这类模式都提供一个方法,将客户从所需要实例化的对象中解耦。
包含:
工厂方法、抽象工厂、单例
2行为型
只要是行为型,都会涉及到类和对象如何交互和分配职责
包含:策略、观察者、命令、状态、迭代、模板方法。
3结构型
可以让你把类和对象组合到更大的结构中。
包含:装饰、适配、外观、组合、代理
我想第一种分类原因应该是从什么导致了变化(可变性)
第二种分类:
按照模式处理的是类还是对象。
1类模式
类模式描述类之间的关系如何通过继承定义。类模式的关系是在编译时建立的。
包含:工厂方法、适配器、模板方法
2对象模式
对象模式描述对象之间的关系,而且主要是利用聚合/组合定义。对象模式的关系通常在运行时建立,而且更加动态,更有弹性。
包含:组合、装饰、迭代、命令、外观、代理、观察者、策略、状态、抽象工厂、单例
这里举例说明:
装饰者看似是为新对象添加了行为,但是却把它放在了结构模式中,原因是因为更强调将某对象包装进另一个对象的方式,是用来组合对象,以提供新的功能。
用模式思考
1保持简单
你的目标应该是简单,而不是“如何在这个问题中应用模式”。
正确的说法是,为了要让你的设计简单且有弹性,有时候使用模式是最好的方法。
2设计模式非万灵丹
你需要考虑到模式对你的设计中其他部分所造成的后果。
3你知道何时需要模式
一旦你确定一个简单方案不能满足你的需要,应该考虑这个问题以及相关的约束-----这可以帮你将问题对应到一个模式中。如果你的经验不足以让你马上确定使用什么模式,你应该花些时间去调查一下。从几个方面入手:意图、应用。如果觉得可能适合,还要进一步判断这个模式带来的后果,以及对其他部分的影响。