# 设计模式
## 1、简单工厂
### 面向接口编程
组件:从设计上讲,组件就是能完成一定功能的封装体。
### 定义
提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。
### 典型疑问
把客户端里面的“new Impl()”移动到简单工厂里面,不还是一样通过new一个实现类来得到接口么?
### 优缺点
优点:帮助封装、解耦
缺点:可能增加客户端的复杂度(根据客户端的参数来选择具体的实现类)、不方便扩展子工厂
### 思考
简单工厂的本质:选择实现
何时选用简单工厂:
1、想要完全封装隔离具体实现,让外部只能通过接口来操作封装体,那么可以选用简单工厂,让客户端通过工厂来获取相应的接口,而无须关心具体的实现。
2、如果想要把对外创建对象的职责集中管理和控制,可以选用简单工厂,一个简单工厂可以创建很多的、不相关的对象,可以把对外创建对象的职责集中到一个简单工厂来,从而实现集中管理和控制。
## 2、外观模式
### 定义
为子系统中的一组接口提供一个一致的界面,Facade模式提供了一个高层接口,这个接口使得这一子系统更加容易使用。
界面:从一个组件外部来看这个组件能看到什么。
接口:外部和内部交互的一个通道。
### 优缺点
优点:1、松散耦合;2、简单易用;3、更好的划分访问的层次
缺点:过多的Facade容易让人迷惑。
### 思考
本质:封装交互,简化调用
何时选用外观模式:
1、希望一个复杂的子系统提供一个简单的接口
2、想要让客户程序和抽象类的实现部分松耦合
3、构建多层结构的系统
## 3、适配器模式
### 定义
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
### 优缺点
优点:1、更好的复用性;2、更好的可扩展性;3、过多的使用适配器,会让系统非常凌乱,不容易整体进行把握。
### 思考
本质:转换匹配,复用功能
何时选用适配器模式:
1、如果你想要使用一个已经存在的类,但是他的接口不符合你的要求
2、如果你想创建一个可以复用的类,这个类可能和一些不兼容的类一起工作
3、如果你想使用一些已经存在的子类,但是不可能对每一个子类都进行适配
## 4、单例模式
### 定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
### 优缺点
1、时间空间
2、线程安全
### 思考
本质:控制实例数目
何时选用适配器模式:
1、需要控制一个类的实例只能有一个,而且客户只能从一个全局访问点访问时
## 5、工厂模式
### 定义
定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到其子类。
### 优缺点
优点:
1、可以在不知道具体实现的情况下编程
2、更容易扩展对象的新版本
3、连接平行的类层次
缺点:
1、具体产品对象和工厂方法的耦合性
### 思考
本质:延迟到子类来选择实现
何时选用工厂模式:
1、如果一个类需要创建一个接口的对象,但是又不知道具体的对象
2、如果一个类本身就希望由它的子类来创建所需的对象
## 6、抽象工厂模式
### 定义
提供一个创建一系列相关或相互依赖对象的接口,而无需指定具体的类。
### 优缺点
优点:1、分离接口和实现;2、使得切换产品簇变得容易
缺点:1、不太容易扩展新的产品;2、容易造成类层次复杂
### 思考
本质:选择产品簇的实现
何时选用工厂模式:
1、如果希望一个系统独立于它的产品创建、组合和表示的时候
2、如果一个系统要由多个产品系列中的一个配置的时候
3、如果强调一系列相关产品的接口,以便联合使用他们的时候
## 7、生成器模式
### 定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
### 优缺点
优点:1、松散耦合;2、可以很容易的改变产品的内部表示;3、更好的复用性;
### 思考
本质:分离整体构建算法和部件构造;
何时选用生成器模式:
1、如果创建对象的算法,应该独立于该对象的组成部分以及他们的装配方式时。
2、如果同一个构建过程有着不同的表示时。
## 8、原型模式
### 定义
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
### 优缺点
优点:1、对客户端隐藏具体的实现类型;2、在运行时动态改变具体的实现类型;
缺点:每个原型的子类,都必须实现clone操作
### 思考
本质:克隆生成对象
何时选用原型模式:
1、如果一个系统想要独立于它想要使用的对象时
2、如果需要实例化的类是在运行时刻动态指定时
## 9、中介者模式
### 定义
用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显示的相互吸引,从而使其耦合松散,而且可以独立的改变他们之间的改变。
### 优缺点
优点:1、松散耦合;2、集中控制交互;3、多对多变成一对多;
缺点:过度集中化
### 思考
本质:封装交互
何时选用中介者模式:
1、如果一组对象之间的通信方式比较复杂,导致相互依赖、结构混乱
2、如果一个对象引用很多的对象,并直接跟这些对象交互,导致难以复用该对象
## 10、代理模式
### 定义
为其他对象提供一种代理以控制对这个对象的访问
### 特点
远程代理:隐藏了一个对象存在于不同的地址空间的事实
虚代理:可以根据需要来创建“大”对象
保护代理:可以在访问一个对象前后增加业务操作
智能指引:访问对象前后增加很多业务操作
### 思考
本质:控制对象访问
何时选用代理模式:
1、需要为一个对象在不同的地址空间提供局部代表的时候,可以使用远程代理。
2、需要按照需要创建开销很大的对象的时候
3、需要控制对原始对象的访问的时候
4、需要在访问对象执行一些附加操作的时候
## 11、观察者模式
### 定义
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
### 优缺点
优点:1、观察者模式实现了观察者和目标之间的抽象耦合;2、观察者模式实现了动态联动;3、观察者模式支持广播通信;
缺点:1、可能会引起无谓的操作;
### 思考
本质:触发联动
何时选用观察者模式:
1、当一个抽象模型有两个方面,当一个方面的操作依赖于另一个方面的状态变化
2、如果在更改一个对象的时候,需要同时连带修改其他对象,而且不知道究竟应该有多少对象应该被连带改变
3、当一个对象必须通知其他对象,但是你又希望这个对象和其他被通知的对象是松散耦合的
## 12、命令模式
### 定义
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
### 优缺点
优点:1、更松散的耦合;2、更动态的控制;3、很自然的复合命令;4、更好的扩展性;
### 思考
本质:封装请求
何时选用命令模式:
1、如果需要抽象出需要执行的动作,并参数化这些对象,可以选用命令模式;
2、如果需要在不同的时刻指定、排列和执行请求,可以选用命令模式;
3、如果需要支持取消操作,可以选用命令模式;
4、如果需要支持当系统崩溃时,能将系统的操作功能重新执行一遍,可以选用命令模式;
5、在需要事务的系统中,可以使用命令模式;
## 13、迭代器模式
### 定义
提供一种方法顺序访问一个聚合对象中的各个元素,而又不需暴露该对象的内部表示
### 优缺点
优点:
1、更好的封装性;
2、迭代器模式可以让你访问一个聚合对象的内容,而无需暴露该聚合对象的内部表示,从而提高聚合对象的封装性;
3、可以以不同的遍历方式来遍历一个聚合;
4、使用迭代器模式,使得聚合对象的内容和具体的迭代算法分离开。这样就可以通过使用不同的迭代器实例、不同的遍历方式来遍历一个聚合对象了,比如上面实例的带迭代策略的迭代器;
5、迭代器简化了聚合的接口;
6、有了迭代器的接口,则聚合本身就不需要再定义这些接口了,从而简化了聚合的接口定义;
7、简化客户端调用;
8、迭代器为遍历不同的聚合对象提供了统一的接口,使得客户端遍历聚合对象的内容更简单;
9、同一个聚合上可以有多个遍历;
10、每个迭代器保持他自己的遍历状态,可以对同一个聚合对象同时进行多个遍历;
### 思考
本质:控制访问聚合对象中的元素
何时选用迭代器模式:
1、如果你希望提供访问一个聚合对象的内容,但是又不想暴露它的内部表示的时候,可以使用迭代器模式来提供迭代器接口,从而让客户端只是通过迭代器的接口来访问聚合对象,而无需关心聚合对象的内部实现;
2、如果你希望有多种遍历方式可以访问聚合对象,可以使用迭代器模式;
3、如果你希望为遍历不同的聚合对象提供一个统一的接口,可以使用迭代器模式;
## 14、组合模式
### 定义
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
### 优缺点
优点:1、定义了包含基本对象和组合对象的类层次结构;2、统一了组合对象和叶子对象;3、简化了客户端调用;4、更容易扩展;
缺点:1、很难限制组合中的组件类型;
### 思考
本质:统一叶子对象和组合对象。
何时选用组合模式:
1、如果你想表示对象的部分-整体层次结构;
2、如果你希望统一的使用组合结构中的所有对象;
## 15、模版方法
### 定义
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
### 优缺点
优点:1、实现代码复用;
缺点:1、算法骨架不容易升级;
### 思考
本质:固定算法骨架;
何时选用模版方法模式:
1、需要固定定义算法骨架,实现一个算法的不变部分,并把可变的行为留给子类;
2、各个子类中具有公共行为;
3、需要控制子类扩展的情况;