# 13. 设计模式
# 表13-1
- 抽象工厂模式 vs 建造者模式
创建方式 完成方式 中间层 受保护的变化 对客户的要求 抽象工厂模式 一步到位 一系列方法 抽象工厂 制作来源 较低 建造者模式 一系列步骤 最后一步 建造者 制作细节 极低
# 表13-2
- 设计模式总结
创建模式 结构模式 行为模式 类 静态工厂
工厂方法适配器(类) 解释器
模板方法对象 抽象工厂
建造者
原型
单例
对象池适配器(对象)
桥梁
复合
装饰器
外观
享元
代理责任链
命令
迭代器
中介者
备忘录
观察者
状态
策略
访问者
# 13.1 创建模式——不要问我从哪里来
接通过构造器来构造对象的缺点:构造器无法多态。
每次调用都伴随对象的的创建,但并不总是合适的,
借助工厂方法可以控制对象创建的实例个数(如单例模式);
另一方面处于性能的考虑,比如可以利用对象池来减少对象的创建,如JAVA中Boolean类提供的valueOf方法。
构造器无法被继承,很多时候客户只关心创建的对象是否能提供某种特定的服务,
即在乎该对象的社会身份——某个抽象的超类型,而不是它的个体身份——具体类型。
如果通过new来创建对象,就必须知道对象的具体类型,从而违背了针对接口编程的原则。
通过工厂方法,可以返回一个具有指定接口的对象,对象的具体类型不透露给客户。
这些类型可以是公开的也可以是非公开的,还可以是运行期间决定的,甚至可以动态加载。
此外,或由于设计上的缺陷,或因对象本身的复杂性,不少构造器并没有完成全部的初始化。
这不仅会给客户带来额外的负担,也可能破坏对象的一致性。更糟糕的是,这部分逻辑随时可能变化,维护起来很不方便。
最好的办法是把这种变化隔离出来,单独封装在一个模块中。这个模块可以是一个方法——工厂方法,也可以是一个类——工厂类。
该模式蕴含了:
间接原则 —— 客户间接通过工厂方法获取对象
单一原则 —— 工厂代表一种变化,也代表一种创建对象的职责
纯虚构原则 —— 工厂类是一个虚构类
关注点分离原则 —— 工厂类把创建对象的关注点分离出来;
依赖原则 —— 客户通过new 来使用构造器有违反依赖反转原则
- 工厂模式
模板方法模式的特点是:定义一个算法骨架,并把某些步骤留给子类去定义。
工厂方法模式可以弥补构造器无法多态的缺憾,因此又被称为虚拟构造模式。
静态工厂模式
抽象工厂模式 P402 图13-2要创建的是一组具有共同主题的对象。故又称为工具箱模式(kit pattern)
工厂方法模式 P402 图13-1
当一个类不愿自行选择或管理所依赖的工厂对象时,可以要求客户通过它的构造器、setter方法等途径来注入,即依赖注射。
如果把创建组件当成一种策略,它还可以视为策略模式的应用。
另一种使用抽象工厂的方式是依赖查找,
即通过查找某个工厂类、服务定位器、注册表、系统环境或上下文等来获取工厂对象。
这种方法减轻了客户的负担,但对查找的对象有产生了依赖。
依赖原则在工厂模式中应用:
其一,工厂方法常用于模板方法中,而后者是一种特殊的控制反转;
其二,抽象工厂的获取常用到依赖注射或依赖查找;
其三,工厂模式的主要目的是为了遵循依赖反转原则。
抽象工厂的特点是用一系列的方法来创建对象,有助于保证一组产品的一致性,同时能轻而易举地在产品系列之间进行切换。
- 建造者模式
特点是用一些列步骤来创建对象。
从间接的角度来讲,抽象工厂模式的中间层是工厂,而创建者模式的中间层是建造者。
区别在于:工厂一步到位地提供产品,而建造者直到最后一步才完成产品。
从保变的角度看,前者保护的变化是产品的制作来源,后者保护的变化是产品的制作细节。
建造者模式与工厂模式可以双管齐下:
建造者在创建产品的过程中,设计的部件可用工厂模式来生成;
工厂模式在生产复杂产品时,又可以建造者模式来分步进行。
建造者模式适合具有稳定组成部分,但建造过程又比较复杂的产品。
相比工厂模式,它的优势在于:对客户的知识要求极低,符合最少知识原则。
工厂模式的客户需要了解所有涉及的产品类型,而建造者模式的客户至多需要了解最终产品的类型。
建造者模式分离了对象创建的过程与对象的结构表示,故能做到工厂模式难以做到的事情。
此外创建者模式还有助于解决构造器参数过长的问题。
P406 图13-3 建造者模式
- 原型模式
直接对原型对象进行拷贝
- 对象池模式
(资源池模式)
它可重复利用已创建的对象,尤其是那些极耗资源或数量受限的对象,比如数据库连接、套接字连接、线程等。
```md
* 单例模式
```md
是极少数不直接依赖继承和多态机制的模式。
可以看成封装的全局变量,它遵循保变原则和局部化原则。
为系统集中提供唯一一个负责某种职责的全局访问点。
# 总结
抽象工厂模式 vs 建造者模式
创建模式,都是为了避免通过构造器来创建对象的底层操作,对创建对象的逻辑进行封装和抽象,以提高软件的灵活应变能力。
表13-1 对象创建的选择方案
类型 子类型多态、参数多态
主体 静态工厂类、工厂对象
方式 构造器、反射(reflecttion)、clone、反序列化(deserialization)、重用
数量 一个(单例)、有限个(对象池)、不限(普通)
形式 实际对象、代理对象
时间 立时(eager)、延迟(lazy)
地点 本地(local)、远程(remote)
服务 本地服务、远程服务