Date: 29 Nov 2014
为了写出高质量的代码,终于开始学习设计模式了。在这片文章中设计模式都是基于面向对象编程语言的,目的在于提高代码可复用性。这次学习倒不是为了能马上用上,只是想增加一点知识储备,在遇到相应的需求时能够拿出优雅的解决方案。笔记的内容主要来自《Design Patterns》这本书。
这个模式主要为工厂方法(Factory Method)定义了一个接口,凡是实现了这一接口的工厂方法都以可以在接受这一接口的方法中被使用,这样就可以灵活地创建不同类型的一组对象。
为创建一个对象而定义接口,这一接口往往定义创建对象的基类,而具体创建对象的类型则由实现了了这一接口的子类来决定。
顾名思义,这个这个模式的就是要把不兼容当前环境的接口转换为可以使用的接口,通常的是实现方法是新建一个类,把含有不兼容接口的类「包装」起来,并在这个类中把这些不兼容的接口转换为可用的接口,而在这个类的外部几乎觉察不到这些不兼容的接口。
在这一模式下,相关的对象将会以树形结构组织起来,从而以整体的形式呈现给使用者。在这个模式中的根对象会把子对象可能行为都定义出来,并且定义好管理树状结构中子对象的方法,而子对象中也有其父对象的引用。在我所接触的程序中运用这一模式的最典型例子就是 Unity 3D 中 GameObject 的实现。
这一模式可以动态地为对象添加一些新的行为,而无需产生新的子类。装饰器继承与需要进行装饰对对象,并保留对原对象引用。在装饰器中需要覆盖原对象的方法。在被覆盖的方法中,先要调用原对象引用中的该方法,然后再添加为该方法添加一些新的行为。
观察者模式,又名订阅者模式,是一种十分常见的设计模式。它在对像之间建立了一种一对多的依赖关系,当一个对象发生了改变时,这种改变将会以广播的形式发送给对它感兴趣的对象。在实现观察者模式时需要注意的事项有:如何管理观察者以及由谁来触发更新。
该模式首先定义了算法的一系列接口和一些组件对象,但是这些接口的实现是通过调用它的组件对象的相关方法。在需要改变算法行为的时候并不需要子类化算法本身,而只需要给他装配上不同的组件即可,这样的话就可以提高程序的灵活性。
在这一模式中,首先在父类中定义了一个算法需要实现的方法以及这些方法的调用顺序(Hook Operation),在父类中只是规定这些方法的默认行为,同时这些方法可以在子类中被重写和扩展,但是调用的顺序还是父类中所定义的顺序,这就保证了算在具有一定扩展性的同时又能保证的大框架的稳定。
这一模式又称为 Action 或者 Transaction,基本思想就是把对 Client 的请求(Request)包装成一个对象,这个对象中还包括了请求的具体操作,最典型的例子就是一些支持回调(Callback)函数的请求。除此之外,Cammand 模式还要支持撤销操作(Undo),这也是它为什么又叫做 Transcation 的原因。要支持撤销操作,这就要求程序要记录下请求的历史记录和状态。
现在很多高级编程语言都原生支持了这一模式,但是这并不妨碍我们去了解它的思想以及采用这种模式的好处。迭代器(Iterator)在不需要了解集合类型内部结构的情况为使用者提供了访问的入口。它的主要思想就是把访问和操作集合类的功能从集合类型中分离出去,把它们封装到迭代器中。这样做的好处之一就是可以实现各种不同的访问、遍历集合类型的算法,而无需改变集合类型本身的结构,真强了程序的灵活性。
当有多个对象之间需要相互通信时,可以使用这一模式来统一管理这些对象之间的通信,把原有的多对多的通信变成一对多的通信,从而达到解除对象之间相互依赖的关系。
这个模式又叫做 Token,其作用是在不破坏和暴露对象内部结构的情况下记录对象的内部状态,从而在需要恢复对象之前的状态时用上。这一模式在实现时一般由三部分组成:Memento、Originator、Caretaker。Memento 就是用来记录对象状态的;Originator 将通过创建 Memento 来记录自己的状态;Caretaker 则是用来保存和管理 Memento 的。
当一个对象的内部状态发生改变时可以同过改变其 State 对象的类型来改变其自身行为,这种模式就称为 State。该模式的组成部分有三个:Context、State 和 ConcreteState Subclasses。Context 要维护和确定其 State 对象的类,不同的 State 类型它体现出来的行为也不同。State 是一个定义了一系列行为接口的抽象类;其中需要注意的是:它一般需要一个状态转换的接口,这样做可以使状态转换的逻辑变得易于改变和维护。ConcreteState subclasses 是继承了 State 抽象类的子类,不同的子类具有不同的行为。采用这种模式的好处是:可以很轻松地添加新的 State,只要实现新的ConcreteState subclasses 即可。
一个对象的内部元素(Element)是各种不同类型的对象,而且这些对象有着不同的接口。当我们想要对这些对象进行相似的访问操作时,可以把这些对不同类型元素的类似操作打包到一个对象中以便维护,这便是 Visitor 模式的主要思想。实现它的关键是双向分发(Double-dispatch),简单理解就是:Element 定义类所能接受的 Visitor 类型,不同类型的 Visitor 的操作种类是不一样的;同时在一种类型的 Visitor 中实现了对不同类型的 Element 的相似操作;所以在 Visitor 模式中的一次访问操作是由 Element 和 Visitor 的类型共同决定的,这就是所谓双向分发。