最近又在翻看GOF的《设计模式-可复用面向对象软件的基础》一书,发现经典就是经典,每次都有新的体验和收获,所以这次把理解和心得写下来,以备学习和交流。
创建型模式抽象了实例化过程,他帮助一个系统独立于如何创建、组合和表示他的那些对象。在Gof 23种经典模式中,主要通过以下方式对实例化过程进行分离和抽象:
1、对象委托。即是将对象的创建委托给专门的工厂对象,这样对于工厂所创建的对象就可以集中进行管理,并向客户端隐藏实际类型信息,客户端所知道的只是所使用(包含)对象的借口,这样当需要对这些对象进行类型、结构调整时就可以非常的方便且统一。如Abstract Factory 和Builder。
2、类继承。即通过在父类中定义创建对象的接口,从而当子类在需要的时候就可以通过重新实现该接口来创建其他类型的对象。如Factory Method。
(注:Factory Method在GOF设计模式中归在对象型模式中,我下一步再继续讨论)
3、实例注入。这种方式的实质是客户端不需要知道所创建/使用的对象的具体类型,而只需要知道在实际运行的时候会得到这些对象的原型,当需要创建对象时仅克隆所得到的原型即可。如Prototype。
至于以上三种方式没有包括的Singleton,我觉得Singleton模式的主要目标并不是对象类型的封装分离,而是为对象的唯一性提供一种保障,且提供一个全局的访问点。
各种模式的相互联系和区别:
1、 Abstract Factory 和 Builder 模式的联系和区别:
抽象工厂和生成器两种模式都是通过委托机制,将创建对象的任务委托给一个其他对象来完成,而向外只提供一个接口。
但是两者的区别还是很大的。
Abstract Factory提供了一个创建一些列相关或相互依赖对象的接口,而无需指定具体的类。它的核心是一系列相关或相互依赖对象,并且这一系列对象可能会因为某种系统属性而变化,比如GOF该模式动机中提到的创建一个支持多种视感标准的用户界面工具包,该工具包中的窗口组件(输入框、滚动条、按钮等)按不同的视感风格要定义不同的外观和行为,这样就不能把这些具体风格相关的组件类型信息硬编码到应用中,而最好应该在应用中只使用抽象组件类型,具体风格相关类型组件的创建封装到抽象工厂的实现中。其他示例如:1,在GOF该模式代码示例中所示的创建不同类型迷宫,不同类型的迷宫组件的创建也是由抽象工厂的实现完成;2,论坛应用中针对不同数据库(sql server或my sql)需要不同的DAO实现,这些DAO也可以通过抽象工厂的具体实现而同一管理。
结构图如下:
Builder的意图是将一个复杂对象的创建和它的表示分离,从而使相同的构建过程可以创建不同的表示。它的核心是针对一个复杂对象的创建,而将创建的过程进行分解分离,比如对一辆汽车的创建,我们就可以将其分解为模型的设计、汽车组件加工、汽车组装三个过程;一幢大厦的建造,我们也同样可以分解为图纸设计、建材选购、建筑施工三个阶段。这样通过分解后,就可以相应对立的对某个阶段/过程进行修改、替换,从而在其他阶段/过程相同的情况下有着不同的对象生成。
结构图如下:
此外对于较复杂对象的创建,Builder模式中也可以引入Abstract Factory模式来为自己创建基本的组件对象,比如我们去配一台台式机,我们就可以把组装电脑的店家看作一个Builder创建器,它根据我们的需要(配置参数)为我们装配所需的电脑,同时电脑所需的部件他又是通过销售商(可以看作抽象工厂的代理)获取,而不是自己创建。
现实世界对象结构图如下:
这个结构图可能会让人比较奇怪,看上去它和GOF中Builder模式的结构图有些不一样,这个结构图缺少Director角色,其实这个区别是很好理解的,因为这个结构图只是现实世界的对象模型,而我们传入的ConfigListing(配置清单)的解析如果用程序来实现,可能就需要增加解析器的角色了。
根据以上理解,所以两种模式的差异就比较明显,Abstract Factory 模式针对一系列对象的创建,这一系列对象受某一系统属性影响;Builder 模式针对一个复杂对象的创建过程,对过程分解,从而可以使各阶段相互独立,使得相同的构建过程可以创建不同的表示,亦可通过不同的构建过程创建由相同表示所构成的不同对象。