# 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)
服务 				本地服务、远程服务