# 基础概念
- 设计模式六大原则
设计模式六大原则](http://www.uml.org.cn/sjms/201211023.asp)
《研磨设计模式》A2.1章节
1. 单一职责原则(SRP)
一个类应该仅有一个引起它变化的原因。
2. 里氏替换原则(LSP)
凡是基类能使用的地方,子类也一定能使用。
3. 依赖倒置原则(DIP)
要依赖于抽象,不要依赖于具体。
倒置接口所有权,就是hollywood原则:不要找我们,我们会联系你。
4. 接口隔离原则(ISP)
接口尽量单一,只代表一个角色。
5. 迪米特法则(最少知识原则LOD)
一个对象应当对其他对象的细节有尽可能少的了解。
6. 开闭原则(OCP)
对扩展开放,对修改关闭。
- 参考资料
- [23种设计模式](https://www.cnblogs.com/beijiguangyong/archive/2010/11/15/2302807.html)
# 已使用模式汇总
- HystixCommand使用了命令模式。
- Prometheus通过适配器模式使用cratedb。
- 适配器模式实现混合云。
- 告警模块使用了观察者模式。
- 对云主机的操作使用命令模式。
- 对菜单和按钮的管理使用组合模式。
- 在混合云控制器中使用模板方法模式。
- shiro和spring security采用了模板方法模式。
- 计费管理、监控系统用策略模式。
- 处理订单状态、审批流程可以使用状态模式。
- 通过备忘录模式实现主机创建失败时的补偿操作。
- 解释器模式,可以解析蓝图定义文件。
- Spring的AOP采用了策略模式,策略是CGLib和JDK动态代理。
# 简单工厂
简单工厂,提供一个创建对象实例的功能,而无须关系其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。
使用简单工厂前的代码:
```java
API api = new Impl();
```
编码时需要知道Impl类。
使用简单工厂后:
```java
API api = Factory.createAPI();
```
```java
public Class Factory {
public static API createAPI() {
API api = new Impl();
}
}
```
# 外观模式
外观模式,即façade模式,为子系统中的一组接口提供一个一致的界面,façade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
使用外观模式前:
![图片](/Users/kaiming/Git/hana/mydoc/images/facade_pattern_01.png)
使用外观模式后:
![图片](/Users/kaiming/Git/hana/mydoc/images/facade_pattern_02.png)
# 工厂方法模式
工厂方法模式(Factory Method),定义一个用于创建对接的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到其子类。
工厂方法模式有点类似IoC。
# 抽象工厂模式
抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
# 适配器模式
适配器模式(Adapter),将一个类的接口转化成客户希望的另外一个接口。适配器模式使得原来由于接口不兼容而不能一起工作的那些类可以一起工作。
适配器模式中的对象:
Client:客户端,调用自己需要的领域接口Target。
Target:定义客户端需要的跟特定领域相关的接口。
Adaptee:已经存在的接口,通常能满足客户端的功能要求,但是接口与客户端要求的特定领域接口不一致,需要被适配。
Adapter:适配器,把Adaptee适配成Client需要的Target。
# 生成器模式
- 定义
生成器模式(Builder),又称为建造者模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
生成器模式的本质是分离构建算法和部件构造。
- 生成器模式与模板方法模式
两者有很多类似的地方,但区别也很明显,首先是模式的目的,生成器模式是用来构建复杂对象的,而模板方法是用来定义算法骨架,尤其是一些复杂的业务功能的处理算法的骨架;其次是模式的实现,生成器模式是采用委托的方法,而模板方法采用的是继承的方式。
# 原型模式
原型模式(Prototype),用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
- Java的Cloneable接口
调用super.clone的方法的时候,Java先开辟一块内存空间,然后把实例对象的值原样拷贝过去。
- 浅度克隆和深度克隆
深度克隆都需要自己实现。
# 中介者模式
中介者模式(Mediator),用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显式的相互引用,从而使其耦合松散,而且可以独立的改变他们之间的交互。
# 代理模式
- 定义
代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问。
Hibernate的Lazy Load就是用代理模式来实现的。
- 静态代理和动态代理
自己实现的代理模式称为静态代理,缺点是subject接口发生变化,则代理类和实现类都要发生变化。
使用Java内建的对代理模式支持的功能称为Java的动态代理,动态代理类始终只有一个invoke方法,当subject接口发生变化的时候,动态代理的接口不需要跟着变化。
# 观察者模式
- 定义
观察者模式(Observer),定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖它的对象都得到通知并被自动更新。
- 观察者模式与订阅/发布模式的区别
观察者模式:
![图片](/Users/kaiming/Git/hana/mydoc/images/observer-pattern-01.png)
发布订阅模式:
![图片](/Users/kaiming/Git/hana/mydoc/images/observer-pattern-02.png)
区别在于观察者模式的具体目标直接持有观察者对象,在目标对象发生变化时,直接通知观察者。
而发布/订阅模式存在调度中心,有调度中心统一处理订阅者注册到调度中心的处理代码。
# 命令模式
命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求进行排队或者记录请求日志,以及支持可撤销的操作。
命令模式的好处:
1、 更松散的耦合
使发起命令的对象(客户端)和具体实现命令的对象(接收者)对象完全解耦
2、 更动态的控制
命令模式把请求封装起来,可以动态的对它进行参数化、队列化和日志化、撤销等操作,从而使得系统更灵活。
3、 很自然的复合操作
命令对象能够很容易的组合成复合命令,也就是前面讲的宏命令,从而使系统操作更简单,功能更强大。
4、 更好的扩展性
由于发起命令的对象和具体的实现完全解耦,因此扩展新的命令就很容易,只需要实现新的命令对象,然后在装配的时候,把具体的实现对象设置到命令对象中,然后就可以使用这个命令对象,已有的实现完全不用变化。
# 迭代器模式
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
# 组合模式
组合模式(Composite),将对象组合成树型结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式通过引入一个抽象的组件对象,作为组合对象和叶子对象的父对象,这样就把组合对象和叶子对象统一起来了,用户使用的时候,始终是在操作组件对象,而不用去区分操作组合对象还是叶子对象。
# 模板方法模式
模板方法模式(Template Methdod),定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
# 策略模式
策略模式(strategy),定义一系列的算法,把他们一个个封装起来,并且使他们可相互替换。本模式使得算法可独立于它的客户而变化。
# 状态模式
状态模式(state),允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
状态模式的本质是根据状态来分离和选择行为。
# 备忘录模式
备忘录模式(memento),在不破坏封装性的前提下,捕获一个对象的内部状态,并在改对象之外保存这个状态,
备忘录模式的本质是保护和恢复内部状态。
- 实现可撤销操作的两种方式
一种是补偿式或者反操作式,比如被撤销的操作是加的功能,那撤销的实现就变成减的功能;被撤销的功能是打开的功能,那撤销的实现就变成关闭的功能。
另一种方式是存储恢复式,把操作前的状态记录下来,要撤销的时候就直接恢复回去。
# 享元模式
享元模式(flyweight),运用共享技术有效的支持大量细粒度的对象。
对象实例的数据的可变部分称为外部状态,不变部分称为内部状态。把内部状态分离出来共享,称之为享元。
JDK中的Integer、Lang、Byte、String等都用到了享元模式。他们的valueOf()方法用到了享元模式,String常量池就是享元模式。
# 解释器模式
解释器模式(interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
# 装饰模式
装饰模式(Decorator)动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更加灵活。
装饰模式的本质是动态组合。
装饰模式和AOP的思路类似。
JDK中的InputStream相关类使用了装饰模式。
# 责任链模式
责任链模式(chain of responsibility),使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
# 桥接模式
桥接模式(Bridge),将抽象部分和它的实现部分分离,使他们都可以独立地变化。
JDK中桥接模式的一个例子是JDBC。
# 访问者模式
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。