对《Head First 设计模式》
中的常用设计模式的整理,其实很多模式我们在开发中都有用到,但是在此之前没有一种理论基础支撑自己,有了这些知识后,更有利于做好程序的设计工作,以及遇到一些设计问题时知道如何取舍。
通过组合不同的算法,为系统提供运行时动态地改变行为的功能,使系统具有更大的弹性。
定义了算法族,把它们分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户之上。
通过使用观察者模式,使多个对象之间松耦合,但是它们依然可以交互,但是不用清楚彼此的细节。
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
装饰者可以在被装饰者的行为前面或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,从而达到某种特定的目的。
动态地将责任附加到对象上。若要拓展功能,装饰者提供了比继承更有弹性的替代方案。
通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。
定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道(或关心)实际产出的具体产品是什么,这样一来,客户就从具体的产品中被解耦。
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
坦白说,工厂方法与抽象工厂的相似度很高,从类图上看很难将它们理清楚,但是从定义上来看的话会发现它们的区别主要是在设计层次上,以我们大家熟悉的电子产品为例,如果有两个产品:手机、电脑,用工厂方法表示苹果和三星的类图:
从品牌的角度上来看,两家厂商生产不同的手机和电脑,这样的工厂方法很清晰;但是如果我们把生产条件做的更细致一点的话,比如苹果面向中国的产品和面向美国的产品是不同的,面向中国大陆销售的产品是阉割过的,而美国的是全功能的,用抽象工厂表示就像这样:
抽象工厂的每一个子类都像是一个工厂方法,就像抽象工厂的定义所说的那样:用于创建相关或依赖对象的家族。
创建一个独一无二的对象。
确保一个类只有一个实例,并提供一个全局访问点。
通过统一的接口操作不同的对象,使系统能够轻易的实现多种目的。
将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
适配器可以将改变的接口封装起来,客户就不必为了应对不同的接口而每次跟着修改。
将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的外观。
提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。这可以确保算法的结构保持不变,同时由子类提供部分实现。
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
让我们能游走于集合中的每一个元素,而又不暴露其内部的表示。
提供一种方法顺序访问一个集合对象中的各个元素,而又不暴露其内部的表示。
能够创建一个树形结构,在同一个结构中处理嵌套菜单和菜单项组。
允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
将状态封装成独立的类,并将动作委托到代表当前状态的对象,使行为随着内部状态而改变。
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
让代理对象控制对某个对象的访问,被代理的对象可以是远程的对象、创建开销大的对象或需要安全控制的对象。
为另一个对象提供一个替身或占位符以控制对这个对象的访问。
代理是个复杂的模式,变种颇多,不同的变种甚至就有不同的类图。