区分那些相似的设计模式
GoF在《Design Patterns: Elements of Reusable Object-Oriented Software》中总结了23种经典的设计模式,成为了该领域的经典。尽管除此之外后来又有人提出了很多其它设计模式,但因为较为零散且有些只针对特定语言,这里暂不涉及。首先,《Design Patterns: Elements of Reusable Object-Oriented Software》一书虽经典,但不适合作为学习设计模式的第一本书。我想一个原因在于书里虽然对每种模式都进行了阐述,但是对它们之间的关联和区别讲得比较少,因此读下来就觉得有些个模式样子长差不多,难以区别。一个模式包括几个要素:名称,问题,方案,效果,它们的总体就好像这个模式的签名一样,一旦其中一项变了,那么它也就变了,有可能就是另一种模式了。所以我们经常能看到方法相同但意图不同的两种模式,或者意图相同方法不同的两种模式。
Template vs. Strategy
这两个是经常被用来比较的模式了。它们的目的一样,即使得对象的行为能够在运行时被改变,不同的是实现。Template模式使用了继承(Inheritance),而Strategy使用了组合(Composition)。稍具体来说,Strategy是通过组合维护了另一个行为对象的引用,需要执行相关任务时就委托(Delegation)给该对象,通过组合不同的被委托对象动态决定行为。Template则是在父类中定义算法框架,但算法中的一些步骤在子类中定义,运行时通过选择不同的子类决定最终行为。
Factory vs. Builder
两者的目的都是为了创建类的实例,区别在于Builder模式中独有的导演角色(Director role),这个角色负责将零件对象组装成整体。它的优点在于导演角色还可以根据不同的需求,通过改变组装过程从而得到不同的结果。这个过程就好像源码,经过预处理,编译,链接等各个环节,最终得到可执行对象一样。Factory则是一站式的服务,直接就给成品。
Visitor vs. Iterator
两者的目的都是遍历,但遍历的结构和方式略有不同。一般地,Visitor遍历复杂结构,如树结构或组合结构等,结构中每个结点可以同构也可以异构,前提是只要提供一个预定的统一访问接口即可。Iterator用于遍历元素类型一致的集合(多是线性结构,当然也可以是非线性结构),不用为每个元素定义统一的访问接口,因为要进行什么操作用户自己决定。
Memento vs. State
这两种模式像的只有名字了,其实没什么关系。前者的目的在于记录对象当前状态,好让以后能够恢复到这一点。后者用于实现状态机。
Adapter vs. Facade
两种模式的形式很像,都是在对象外面包了层东西,而且都以改变原有接口为目的。区别在于前者一般只包装一个对象,目标是为了改变接口来适应外部系统,现实中的经典例子如电器插头,你英式的插头要进美式的插座就得用个转换器,但要完成的功能没变。而后者一般是将一个子系统进行包装,目的是简化接口,如汽车构造虽然复杂,但暴露给司机的接口-方向盘和油门刹车却很简单,功能也没变,只是用户操作更方便了。
Decorator vs. Adapter
两者形式上也很像,也都是在对象外包一层东西,但目的不一样,前者是为了给现有对象增加功能,一般不改变其接口,如Java I/O就大量使用了这一模式。后者是为了改变其接口,功能保持不变。
State vs.Strategy
这两者在目的上没什么关系,但形式上却是一样的,都是将任务委托给其组合的对象。
Decorator, Adapter vs. Proxy
前两者包装即有对象,要么增加其行为,要么改变其接口。而相比而言,Proxy既不改变原有对象的行为也不会改变其接口,它的核心在于对被代理对象的控制。控制的目的可能是权限控制,虚拟化或者Cache等。还有个细微的区别是Proxy模式中代理对象和被代理对象可以是远程连接的,而Decorator中装饰对象/被装饰对象,Adapter中适配对象和被适配对象一般都在本地。
Abstract factory & Factory
Factory Method定义创建对象的接口,而将创建对象实例的过程放到子类中去定义,用户根据需要选择相应的工厂子类就行。可以看到,Factory模式本身还是Template模式的一种用法。Abstract Factory与之区别在于它是要创建一族相互关联或者依赖的产品。Abstract Factory需要定义所有具体工厂的接口,即它是“工厂的工厂”,每个具体的工厂都要实现其中的方法。Abstract factory用于创建一族相关的产品。如鼠标和键盘,工厂A既可以生产鼠标也可以生产键盘,工厂B也既可以生产鼠标也可以生产键盘,只是它们的实现不一样,如一个是生产无线鼠标键盘而另一个可以是生产有线鼠标键盘的。但你单独拿出一个产品(即鼠标或者键盘)来看,那就是个Factory模式。
Factory vs. Prototype
Factory是从类重新实例一个对象,Prototype是从已有的实例直接拷贝生成一个实例,从而省去了初始化的过程。Prototype模式一般以clone()这种深拷贝函数的形式出现。
Memento vs. Command
两种模式都可以提供回到先前某点的功能,但前者是针对对象状态,后者针对对象行为。前者相当于为对象取一个snapshot,方便以后可以回到该点。正是这个特点,Memento模式也可用于对象序列化及反序列化。后者则通过类似于“撤消”(Undo)的动作来回滚之前动作的影响。
补充:综合编程 , 其他综合 ,