引子
让大脑就范的方法:
(1)慢一点,你理解的越多,需要记的就越少。
(2)勤做练习,自己记笔记。
(3)阅读“There are no Dumb Questions”部分。
(4)上床睡觉之前不要再看别的书了,或者至少不再看其他有难度的东西。
(5)要喝水,而且要多喝点水。
(6)大声说出来。
(7)听听你的大脑怎么说。
(8)要有点感觉。
(9)设计一些东西。
1 设计模式入门
设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
设计原则:针对接口编程,而不是针对实现编程。
针对接口编程的真正的意思是针对超类型编程
有一个 可能比 是一个更好
设计原则:多用组合,少用继承。
策略模式:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计模式让你和其他开发人员之间有共享的词汇。
2 观察者模式
观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖都会收到通知并自动更新。
设计原则:为了交互对象之间的松耦合设计而努力。
3 装饰对象
设计原则:类应该对扩展开放,对修改关闭。
装饰者对象:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
4 工厂模式
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
设计原则:要依赖抽象,不要依赖具体类。
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
5 单件模式
单件模式:确保一个类只有一个实例,并提供一个全局访问点。
6 命令模式——封装调用
把方法调用封装起来
命令模式:将请求封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
7 适配器模式与外观模式——随遇而安
OO适配器与真实世界的适配器扮演着同样的角色:将一个接口转换成另外一个接口,以符合客户的期望。
适配器工作起来就如同一个中间人,它将客户发出的请求转换成厂商类能理解的请求。
适配器模式:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
外观模式,之所以这么称呼,是因为它将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的外观。
外观和适配器可以包装许多类,但是外观的意图是简化接口,而适配器的意图是将接口转换成不同接口。
外观模式:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
设计原则:最少知识原则:只和你的密友谈话。
8 模板方法模式——封装算法
模板方法定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。
模板方法模式:在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
这个模式是用来创建一个算法的模板。什么是模板?如你所见的,模板就是一个方法。更具体地说,这个方法将算法定义成一个步骤,其中的任何步骤都可以是抽象的,由子类负责实现。这可以确保算法的结构保持不变,同时由子类提供部分实现。
好莱坞原则:别调用(打电话给)我们,我们会调用(打电话给)你。
好莱坞原则可以给我们一种防止“依赖腐败”的方法。
策略模式和模板方法模式都封装算法,一个用组合,一个用继承。
9 迭代器与组合模式——管理良好的集合
迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露其内部的表示。
把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。
设计原则:一个类应该只有一个引起变化的原因。
这个原则告诉我们,尽量让每个类保持单一责任。
类的每个责任都有改变的潜在区域。超过一个责任,意味着超过一个改变的区域。
组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
组合模式让我们能用树形方式创建对象的结构,树里面包含了组合以及个别的对象。
使用组合结构,我们能把相同的操作应用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。
10 状态模式
策略模式和状态模式是双胞胎,在出生时才分开。
如何对对象内的状态建模——通过创建一个实例变量来持有状态量,并在方法内书写条件代码来代理不同状态。
状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
11代理模式——控制对象访问
你的客户对象所做的就像是在做远程方法调用,但其实只是调用本地堆中的“代理”对象上的方法,再由代理处理所有网络通信的低层细节。
代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
使用代理模式创建代表对象,让代表对象控制某对象的访问,被代理的对象可以是远程的对象、创建开销大的对象或需要安全控制的对象。
代理对象有许多变体,例如:缓存代理、同步代理、防火墙代理和写入时复制代理。
12复合模式——模式的模式
模式通常会被一起使用,并被组合在同一个设计解决方案中。
复合模式在一个解决方案中结合两个或多个模式,以解决一般或重复发生的问题。
如果猫王是复合模式,他的名字将是Model-View-Controller。
13 与设计模式相处——真实世界中的模式
模式是在某情境下,针对某问题的某种解决方案。
情境就是应用某个模式的情况。这应该是会不断出现的情况。
问题就是你想在某情境下达到的目标,但也可以是某情境下的约束。
解决方案就是你所追求的:一个通用的设计,用来解决约束、达到目标。
如果你发现自己处于某个情境下,面对着所欲达到的目标被一群约束影响着的问题,然而,你能够应用某个设计,克服这些约束并达到该目标,将你领向某个解决方案。
当一个设计模式作家的条件:
做好家庭作业。
花时间反思与评估。
将你的想法写在纸上,好让其他人能够理解。
让其他人使用你的模式,然后继续改进。
不要忘了三次规则。
反模式告诉你如何采用一个不好的解决方案解决一个问题。
反模式看起来总像是一个好的解决方案,但是当它真正被采用后,就会带来麻烦。
附录A——剩下的模式
桥接:使用桥接模式不只改变你的实现,也改变你的抽象。
生成器模式:封装一个产品的构造过程,并允许按步骤构造。
责任链:当你想要一个以上的对象有机会能够处理某个请求的时候,就使用责任链模式。
蝇量:如想让某个类的一个实例能用来提供许多“虚拟实例”,就使用蝇量模式。
解释器模式:为语言创建解释器。
中介者模式:使用中介者模式来集中相关对象之间复杂的沟通和控制方式。
备忘录:当你需要让对象返回之前的状态时,就使用备忘录模式。
原型:当创建给定类的实例的过程很昂贵或很复杂时,就使用原型模式。
访问者:当你想要为一个对象的组合增加新的能力,且封装并不重要时,就使用访问者模式。