先言
- 设计模式,Design Pattern
- 代表了最佳的实践,面向对象的软件开发
- 是为了重用代码、让代码更容易被他人理解、保证代码可靠性
- 设计模式使代码编写真正工程化,是软件工程的基石
- GOF, Gang of Four
- Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides
- 《Design Patterns - Elements of Reusable Object-Oriented Software》
- 面向对对象设计原则
- 对接口编程而不是对实现编程
- 优先使用对象组合而不是继承
- 六大原则
- 开闭原则,Open Close Principle
- 对扩展开放,对修改关闭
- 在程序需要进行扩展的时候,不能去修改原有代码,实现一个热插拔的效果
- 里氏代换原则,Liskov Substitution Principle
- 任何基类可以出现的地方,子类一定可以出现
- 面向对象设计的基本原则之一,是对开闭原则的补充,实现开闭原则的关键步骤是抽象化
- 是继承复用的基石,只有当派生类可以替换基类,且软件单位功能不受到影响,基类才能真正被复用,而派生类也能在基类的基础上增加新的行为
- 依赖倒转原则,Dependence Inversion Principle
- 针对接口编程,依赖于抽象而不是依赖于具体
- 开闭原则的基础
- 接口隔离原则,Interface Segregation Principle
- 使用多个隔离的接口,比使用单个接口要好,即降低类之间的耦合度
- 迪米特法则,又称最少知道原则,Demeter Principle
- 一个实体应当尽量少地与其他实体类之间发生相互作用,使得系统功能模块相对独立
- 合成复用原则,Composite Reuse Principle
- 尽量使用合成/聚合的方式,而不是使用继承
- 开闭原则,Open Close Principle
- 设计模式之间的关系
- UML类图
- 类(class)-矩形框
- 第一层,为类名,如果是抽象类就用斜体
- 第二层,为类的特性,通常为字段和属性
- 第三层,为类的操作,通常为方法,‘=’表示public,‘-’表示private,‘#’表示protected
- 接口(interface)-矩形框
- 第一层,《interface》+接口名
- 第二层,接口方法
- 继承(extends)-空心三角形+实线
- 实现(implements)-空心三角形+虚线
- 关联(has-a)-实线箭头
- 聚合(aggregation,has-a[])-空心菱形+实线箭头
- 合成(composition)—实心菱形—实线箭头
- 依赖(dependency)—虚线箭头
常用模式
Reactor 反应堆设计模式
- 类(class)-矩形框
创建型模式
- 提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new运算符直接实例化对象,这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活
- 当一个系统应该独立于它的产品创建、构成和表示时,应该考虑使用创建型模式
建立相应数目的原型并克隆它们通常比每次用合适的状态手工实例化该类更方便一些
工厂模式,Factory
定义一个用于创建对象的接口,让子类决定实例化哪个类,工厂方法使一个类的实例化延迟到其子类
- 工厂方法模式克服了简单工厂模式违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点

-
抽象工厂模式,Abstract Factory
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
- 接口是负责创建一个相关对象的工厂,不需要显示指定它们的类,每个生成的工厂都能按照工厂模式提供对象

-
单例模式,Singleton
保证一个类仅有一个实例,并提供一个访问它的全局访问点
- 创建型模式,涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建
- 该类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象
- 单例类只能有一个实例;单例类必须自己创建自己的唯一实例;单例类必须给其他所有对象提供这一实例
- 一个全局使用的类频繁的创建与销毁
单例模式的几种实现方式懒汉式,线程不安全private static Singleton instance = null;if(instance == null)懒汉式,线程安全加锁会影响效率,效率很低,99%情况下不需要同步public static synchronized Singleton getInstance(){}饿汉式,线程安全容易产生垃圾对象,类加载时就初始化基于 classloader机制避免了多线程的同步问题private static Singleton instance = new Singleton();双检锁/双重校验锁,DCL,double-checked lockingJDK1.5,采用双锁机制,安全且在多线程情况下能保持高性能getInstance()的性能对应用程序很关键private volatile static Singleton singleton;if(singleton == null){synchronized(Singleton.class){if(singleton == null)singleton = new Singleton();}}登记式/静态内部类可以达到双检锁方式一样的效果,但实现更简单对静态域使用延迟初始化,这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用使用 classloader机制来保证初始化 instance时只有一个线程这种方式是 Singleton类被装载了,instance不一定被初始化,因为 SingletonHolder类没有被主动使用,只有通过显式调用 getInstance()方法时,才会显式装载 SingletonHolder类,从而实例化 instanceprivate static class SingletonHolder {private static final Singleton INSTANCE = new Sngleton();}return SingletonHolder.INSTANCE枚举实现单例模式的最佳方法,更简洁,自动支持序列化机制,绝对防止多次实例化,防止反序列化重新创建新的对象public enum Singleton{INSTANCE;public void whateverMethod(){}}
建造者模式,Builder
- 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创造不同的表示
- 使用多个简单地对象一步一步构建成一个复杂对象,Builder类独立于其他对象
- 建造者模式更加关注与零件装配的顺序

-
原型模式,Prototype
创建型模式,用于创建重复的对象,同时又能保证性能
- 该模式实现了一个原型接口,该接口用于创建当前对象的克隆
- 当直接创建对象的代价比较大时,则采用这种模式
- 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
- 在运行期建立和删除原型
- 与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象
- 浅拷贝实现 Cloneable,重写;深拷贝通过实现 Serializable读取二进制流

-
结构型模式
关注类和对象的组合,继承的概念被用来组合接口和定义组合对象获得新功能的方式
适配器模式,Adapter

-
桥接模式,Bridge
用于把抽象化与实现化解耦,使得二者可以独立变化
- 该模式涉及一个作为桥接的接口,使得实体类的功能独立于接口实现类,这两种类型的类可被结构化改变而互不影响

-
过滤器模式,Filter/Criteria
结构型模式,结合多个标准来获得单一标准
- 允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把他们连接起来
-
组合模式,Composite
创建了对象组的属性结构
- 用于把一组相似的对象当作一个单一的对象,依据树形结构来组合对象,用来表示部分以及整体层次
- 该模式创建了一个包含自己对象组的类,该类提供了修改相同对象组的方式
- 将对象组合成树形结构以表示”部分-整体“的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性
- 在树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦

-
装饰器模式,Decorator
作为现有类的一个包装
- 允许向一个现有的对象添加新的功能,同时又不改变其结构
- 该模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能
- 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更为灵活
- 一般的,为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并随着扩展功能的增多,子类会很膨胀

-
外观模式,Facade
结构型模式,向现有的系统添加一个接口,来隐藏系统的复杂性
- 隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口
- 该模式涉及一个单一的类,该类提供了客户端请求的简化方式和对现有系统类方法的委托调用
- 为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
- 降低访问复杂系统的内部子系统时的复杂度,简化了客户端与之的接口
- 在层次化结构中,可以使用外观模式定义系统中每一层的入口

-
享元模式,Flyweight
结构型模式,提供了减少对象数量从而改善应用所需的对象结构的方式
- 主要用于创建对象的数量,以减少内存占用和提高性能
- 该模式尝试重用现有的同类对象,如未找到匹配对象,则创建新对象
- 运用共享技术有效地支持大量细粒度的对象
- 在有大量对象时,有可能会造成内存溢出,把其中共同的部分抽象出来,如有相同的业务请求,直接返回在内存中已有的对象避免重新创建
- 注意划分外部状态和内部状态,否则可能会引起线程安全问题
- 这些类必须有一个工厂对象加以控制

-
代理模式,Proxy
一个类代表另一个类的功能,向外界提供该类的功能接口,属于结构型模式
- 适配器模式主要改变所考虑对象的接口,代理模式不能改变所代理类的接口
- 装饰器模式为了增加功能,而代理模式为了加以控制

-
行为型模式
-
责任链模式,Chain of Responsibility
为请求创建了一个接受者对象的链
- 该模式基于请求的类型,对请求的发送者和接受者进行解耦
- 该模式通常每个接受者都包含对另一个接受者的引用,如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接受者,依次类推
- 避免请求发送者与接受者耦合在一起,让多个对象都有可能接受请求,将这些对象连接成一条链,并沿着这条链传递请求,直到有对象处理它为止
- 责任链上的处理着负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理着解耦了

-
命令模式,Command Pattern
一种数据驱动的设计模式
- 请求以命令的形式包裹在对象中,并传给调用对象
- 调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令
- 将一个请求封装成一个对象,从而可以用不同的请求对客户进行参数化
- 在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适

-
解释器模式,Interpreter
行为型模式,提供了评估语言的语法或表达式的方式
- 该模式实现了一个表达式接口,该接口解释一个特定的上下文,这种模式被用在 SQL解析、符号处理引擎等
- 给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子
- 对于一些固定文法构建一个解释句子的解释器
- 可利用场景比较少,Java中如果碰到可以用 expression4J代替

-
迭代器模式,Iterator
行为型模式
- 该模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示
- 提供一种方法顺序访问一个聚合对象中各个元素,而又无需暴露该对象的内部表示
- 不同的方式来遍历整个整合对象
- 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,有可让外部代码透明地访问集合内部的数据

-
中介者模式,Mediator
行为型模式,用来降低多个对象和类之间的通信复杂性
- 该模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护
- 用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
- 对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,也需要跟踪与之相关联的对象,同时做出相应的处理


-
备忘录模式,Memento
行为型模式,保存一个对象的某个状态,以便在适当的时候恢复对象
- 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态
- 所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态
- 为了符合迪米特原则,还要增加一个管理备忘录类;为了节约内存,可使用原型模式 + 备忘录模式

-
观察者模式,Observer

-
状态模式,State
行为型模式,类的行为是基于它的状态改变的
- 该模式中,创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context对象
- 允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类
- 对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为

-
空对象模式,Null Object
行为型模式,一个空对象取代 NULL对象实例的检查,NULL对象不是检查空值,而是反映一个不做任何动作的关系,也可以在数据不可用的时候提供默认的行为
- 该模式中,创建一个指定何种要执行的操作的抽象类和扩展该类的实体类,还创建一个未对该类做任何实现的空对象类,该空对象类将无缝地使用在需要检查空值的地方
-
策略模式,Strategy
行为型模式,一个类的行为或算法可以在运行时改变
- 该模式中,创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context对象
- 策略对象改变 context对象的执行算法
- 定义一系列的算法,把它们一个个封装起来,并使它们可相互替代
- 在有多种算法相似的情况下,使用 if…esle所带来的复杂和难以维护
- 如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题

-
模板模式,Template
行为型模式,一个抽象类公开定义了执行它的方法的方式/模板,它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行
- 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中
- 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
- 一些方法通用,却在每一个子类都重新写了这一方法
- 为防止恶意操作,一般模板方法都加上 final关键字

-
访问者模式,Visitor
行为型模式,使用了一个访问者类,改变了元素类的执行算法,通过这种方式,元素的执行算法可以随着访问者改变而改变
- 该模式中,元素对象已接受访问者对象,这样访问者就可以处理元素对象上的操作
- 主要将数据结构与数据操作分离
- 稳定的数据结构和易变的操作耦合问题

-
J2EE设计模式
-
MVC模式,MVC
应用于应用程序的封层开发
- Model,模型,代表一个存取数据的对象或 Java POJO,也可以带有逻辑,在数据变化时更新控制器
- View,视图,代表模型包含的数据的可视化
- Controller,控制器,作用于模型和视图上,控制数据流向模型对象,并在数据变化时更新视图,它使视图与模型分离

-
业务代表模式,Business Delegate
用来减少通信或对表示层代码中的业务层代码的远程查询功能
- 客户端,Client,表示层代码可以是 JSP、servlet、UI Java代码
- 业务代表,Business Delegate,一耳光为客户端实体提供的入口类,提供了对业务服务方法的访问
- 查询服务,LookUp Service,查找服务对象负责获取相关的业务实现,并提供业务对象对业务代表对象的访问
- 业务服务,Business Service,业务服务接口,实现了该业务服务的实体类,提供了实际的业务实现逻辑
-
组合实体模式,Composite Entity
用在 EJB持久化机制中,一个组合实体是一个 EJB实体 bean,代表了对象的图解
- 当更新一个组合实体时,内部依赖对象 beans 会自动更新,因为它们是由 EJB 实体 bean 管理的
- 组合实体 bean 的参与者
- 组合实体(Composite Entity) - 它是主要的实体 bean。它可以是粗粒的,或者可以包含一个粗粒度对象,用于持续生命周期
- 粗粒度对象(Coarse-Grained Object) - 该对象包含依赖对象。它有自己的生命周期,也能管理依赖对象的生命周期
- 依赖对象(Dependent Object) - 依赖对象是一个持续生命周期依赖于粗粒度对象的对象
- 策略(Strategies) - 策略表示如何实现组合实体
-
数据访问对象模式,Data Access Object
用于把低级的数据访问 API 或操作从高级的业务服务中分离出来
- 数据访问对象模式的参与者
- 数据访问对象接口(Data Access Object Interface) - 该接口定义了在一个模型对象上要执行的标准操作
- 数据访问对象实体类(Data Access Object concrete class) - 该类实现了上述的接口。该类负责从数据源获取数据,数据源可以是数据库,也可以是 xml,或者是其他的存储机制
- 模型对象/数值对象(Model Object/Value Object) - 该对象是简单的 POJO,包含了 get/set 方法来存储通过使用 DAO 类检索到的数据
-
前端控制器模式,Front Controller
是用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理
- 该处理程序可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序
- 模式实体
- 前端控制器(Front Controller) - 处理应用程序所有类型请求的单个处理程序,应用程序可以是基于 web 的应用程序,也可以是基于桌面的应用程序
- 调度器(Dispatcher) - 前端控制器可能使用一个调度器对象来调度请求到相应的具体处理程序
- 视图(View) - 视图是为请求而创建的对象
-
拦截过滤模式,Intercepting Filter
用于对应用程序的请求或响应做一些预处理/后处理
- 定义过滤器,并在把请求传给实际目标应用程序之前应用在请求上
- 过滤器可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序
- 模式实体
- 过滤器(Filter) - 过滤器在请求处理程序执行请求之前或之后,执行某些任务
- 过滤器链(Filter Chain) - 过滤器链带有多个过滤器,并在 Target 上按照定义的顺序执行这些过滤器
- Target - Target 对象是请求处理程序
- 过滤管理器(Filter Manager) - 过滤管理器管理过滤器和过滤器链
- 客户端(Client) - Client 是向 Target 对象发送请求的对象
-
服务定位模式,Service Locator
用在我们想使用 JNDI查询定位各种服务的时候
- 考虑到为某个服务查找 JNDI 的代价很高,服务定位器模式充分利用了缓存技术
- 在首次请求某个服务时,服务定位器在 JNDI 中查找服务,并缓存该服务对象
- 当再次请求相同的服务时,服务定位器会在它的缓存中查找,这样可以在很大程度上提高应用程序的性能
- 模式实体
- 服务(Service) - 实际处理请求的服务。对这种服务的引用可以在 JNDI 服务器中查找到
- Context / 初始的 Context - JNDI Context 带有对要查找的服务的引用
- 服务定位器(Service Locator) - 服务定位器是通过 JNDI 查找和缓存服务来获取服务的单点接触
- 缓存(Cache) - 缓存存储服务的引用,以便复用它们
- 客户端(Client) - Client 是通过 ServiceLocator 调用服务的对象
-
传输兑现模式,Transfer Object
用于从客户端向服务器一次性传递带有多个属性的数据
- 传输对象也被称为数值对象,传输对象是一个具有 getter/setter 方法的简单的 POJO 类,它是可序列化的,所以它可以通过网络传输
- 它没有任何的行为。服务器端的业务类通常从数据库读取数据,然后填充 POJO,并把它发送到客户端或按值传递它
- 对于客户端,传输对象是只读的,客户端可以创建自己的传输对象,并把它传递给服务器,以便一次性更新数据库中的数值
- 模式实体
- 业务对象(Business Object) - 为传输对象填充数据的业务服务
- 传输对象(Transfer Object) - 简单的 POJO,只有设置/获取属性的方法
- 客户端(Client) - 客户端可以发送请求或者发送传输对象到业务对象




