设计模式(下)

  1. 外观模式

定义:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。

 

    1. 类图

 

    1. 精要
      1. 设计原则

 

      1. 适用场景

如需要一个高层接口,内部提供多种实现,则可以将这些实现的实例封装到高层接口中,对外提供统一的高层接口。

    1. 典型应用

slf4j中使用较多

  1. 模板方法模式

定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

适用场景:

 

    1. 类图

 

    1. 精要

模板方法模式,在父类中定义了模板方法,这个方法定义了一组不会变的步骤,里面的细节可以在父类就确定而实现的,也可以在子类才实现,这样做的好处是确保了算法的结构保持不变,而又可以随子类有具体的实现。

注意钩子方法

      1. 设计原则

 

      1. 适用场景

 

    1. 典型应用
      1. MyBatis中的模板方法模式

(1)BaseExecutor

采用了模板方法模式,实现了大部分的SQL执行逻辑

(2)SimpleExecutor

每执行一次update或select,就开启一个Statement/PrepareStatement对象,用完立刻关闭。

ReuseExecutor:执行update或select,以sql作为key查找Stetement对象,存在就使用,不存在就创建,用完不关闭,而是放到Map<String,Statement>,供下一次使用。

BatchExecutor:执行update(JDBC不支持批处理select),将所有sql都添加到批处理(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement/PrepareStatement对象。

(3)BaseTypeHandler

 

(4)IntegerTypeHandler

设计模式(下)

 

      1. Spring中的模板方法模式

Spring的JDBC模板即是采用的目标方法模式

  1. 迭代器模式

定义:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

适用场景:

不同的类方法返回的数据集合不同,如一个返回ArrayList集合,另一个返回数组,但是需要在一个地方展示这2个数据。

迭代器让我们能够游走于聚合内部的每一个元素,而不暴露其内部的表示

    1. 类图

《设计模式》P337

    1. 精要

 

    1. 相关设计原则

一个类应该只有一个引起变化的原因

    1. 典型应用

MyBatis中的迭代器模式

PropertyTokenizer类实现了Iterator接口

 

  1. 组合模式

定义:允许你将对象组合成树形结构来表现“整体/部分”层次。组合能让客户以一致的方式处理个别对象以及对象组合。

适用场景:

    1. 类图

 

    1. 精要

 

    1. 典型应用
      1. MyBatis中的组合模式

SqlNode和各个子类ChooseSqlNode等

MyBatis支持动态sql,DynamicSqlSource.getBoundSql方法里,调用了rootSqlNode.apply(context)方法,apply()是SqlNode接口的方法,所有动态节点都实现了SqlNode接口。实现了该接口的所有节点就是整个组合模式树的各节点

  1. 代理模式

定义:

适用场景:

    1. 类图

 

    1. 精要

 

    1. 典型应用
      1. MyBatis中的代理模式

JDK动态代理

MapperProxy

ConnectionLogger

Executor.loader包使用了cglib或javassist达到延迟加载的效果

 

MapperProxy类实现了InvocationHandler接口,并实现了invoke方法

Spring中的代理模式

Spring中代理模式最典型的应用就是AOP,实现AOP主要有2种方式,JDK和Cglib

JdkDynamicAopProxy

CglibAopProxy(Spring4之前的是Cglib2AopProxy)

  1. 桥接模式

桥接模式不只改变实现,还改变抽象

    1. 类图

 

    1. 精要

 

    1. 典型应用

 

    1. 比较

桥接模式的优点:

(1)将实现予以解耦

(2)抽象和实现可以独立扩展

(3)对于“具体的抽象类”所做的改变,不会影响客户

用途和缺点:

(1)适合使用在需要跨越多个平台的图形和窗口系统上

(2)适用在需要不同的方式改变接口和实现的场景

(3)增加了复杂度

 

桥接模式与策略模式比较:

个人理解:策略模式更接近于面向对象的多态,通过子类来决定具体的行为。而桥接模式在使用侧多了一层抽象,在这个抽象的实现中,在调用时决定该采用的具体桥梁。

  1. 生成器模式

封装一个产品的构造过程,并允许按步骤构造。

适用场景:构建对象时,如果累的参数很多,且其中很多参数类型相同并且很多参数可以为空时,适用Builder模式会更好。

    1. 类图

 

    1. 精要

 

    1. 典型应用

如参数非常多的场景,比如一个类的实例变量很多,如果在构造函数中传很多实参来创建对象,将会变得非常之复杂。

      1. Mybatis中的生成器模式

Mybatis中的Builder模式

 

 

(1)XMLConfigBuilder

XMLConfigBuilder用于读取MyBatisMapConfig.xml和所有的*Mapper.xml文件,即Mybatis的配置文件(配置了全局参数等)和SQL的配置文件(配置了SQL语句),构建MyBatis运行的核心对象Configuration。在构建Configuration对象时,还会调用XMLMapperBuilder

 

(2)XMLMapperBuilder

XMLMapperBuilder用于读取*Mapper文件,会使用到XMLStatementBuilder。

 

(3)XMLStatementBuilder

XMLStatementBuilder用于读取和build所有的SQL语句

 

(4)SqlSessionFactoryBuilder

SqlSessionFactoryBuilder会调用XMLConfigBuilder,Configuration对象会作为构建SqlSessionFactory的参数

 

(5)CacheBuilder

 

在这些Builder的过程中,会读取文件或配置,做大量的XpathParser解析、配置或语法的解析、反射生成对象、存入结果缓存等步骤,单纯的构造函数无法完成。

    1. 比较

生成器的优点

(1)将一个复杂对象的创建过程封装起来

(2)允许对象通过多个步骤来创建,并且可以改变过程(这和只有一个步骤的工程模式不同

(3)向客户隐藏产品内部的表现

(4)产品的实现可以被替换,因为客户只看到一个抽象的接口

生成器的用途和缺点

(1)经常被用来创建组合结构

(2)与工厂模式相比,采用生成器模式创建对象的客户,需要具备更多的领域知识

 

  1. 责任链模式

让一个以上的对象有机会能够处理某个请求

    1. 类图

 

    1. 精要

 

    1. 典型应用

 

    1. 比较

责任链的优点:

(1)将请求的发送者和接受者解耦

(2)简化对象,不需要知道链的结构

(3)通过动态改变链内的成员或调动它们的次序,允许动态地新增或删除责任

用途和缺点:

(1)经常被使用在窗口系统中,处理鼠标和键盘之类的事件

(2)并不保证请求一定会被执行;如果没有任何对象处理它,可能会落到链尾之外

(3)可能不容易观察运行时的特征,有碍于除错

 

  1. 蝇量模式

让某个类的一个实例能用来提供许多“虚拟实例”。

    1. 类图

 

    1. 精要

 

    1. 典型应用

 

    1. 比较

蝇量的优点:

(1)减少运行时对象实例的个数,节省内存

(2)将许多“虚拟”对象的状态集中管理

用途和缺点:

(1)当一个类有许多的实例,而这些实例能被同一方法控制的时候,可以用蝇量模式

(2)一旦实现了它,那么单个的逻辑实例将无法拥有独立而不同的行为

 

  1. 解释器

为语言创建解释器

    1. 类图

 

    1. 精要

 

    1. 典型应用

 

    1. 比较

计时器模式的优点:

(1)将每一个语法规则表示成一个类,方便于实现语言

(2)语法由许多类表示,可以轻易地改变或扩展

(3)通过在类结构中加入新方法,可以在解释的同时增加新行为,例如打印格式的美化或进行复杂的程序验证

用途和缺点:

(1)当需要实现简单的语言时,使用解释器

(2)当有简单的语法,而且简单比效率重要时,使用解释器

(3)可以处理脚本语言和编程语言

(4)当语法规则的数目太大时,会变得非常复杂。此时,使用解析器/编译器的产生器可能更合适

 

  1. 中介者模式

集中相关对象之间复杂的沟通和控制方式

    1. 类图

 

    1. 精要

 

    1. 典型应用

 

    1. 比较

中介者模式的优点:

(1)将对象彼此解耦,增加对象的复用性

(2)集中控制逻辑,简化系统维护

(3)让对象之间锁传递的消息变得简单而大幅减少

用途和缺点:

(1)常常被用来协调相关的GUI组件

(2)如果设计不当,中介者对象本身会变得过于复杂

 

  1. 备忘录模式

需要让对象返回之前的状态时,使用备忘录模式

    1. 类图

 

    1. 精要

 

    1. 典型应用

 

    1. 比较

备忘录模式的优点:

(1)将被存储的状态放在外面,不和关键对象混在一起,帮助维护内聚

(2)保持关键对象的数据封装

(3)提供容易实现的恢复能力

用途和缺点:

(1)用于存储状态

(2)存储和灰度状态的过程肯呢个相当耗时

(3)在Java系统中,可以考虑使用序列化(serialization)机制存储系统的状态

 

  1. 原型模式

当创建给定类的实例的过程很昂贵或很复杂时,使用原型模式

 

    1. 类图

 

    1. 精要

有一个原型实例,需要基于这个实例产生新实例时,可使用原型模式

    1. 典型应用

 

    1. 比较

原型模式的优点:

(1)向客户隐藏制造实例的复杂性

(2)提供让客户能够产生未知类型对象的选项

(3)在某些环境下,复制对象比创建新对象更有效

用途和缺点:

(1)在一个复杂的类层次中,当系统必须从其中的许多类型创建新对象时,考虑原型模式

(2)对象的复制有时相当复杂

 

  1. 访问者模式

为一个对象的组合增加新能力,且封装不重要时,使用访问者模式

    1. 类图

 

    1. 精要

 

    1. 典型应用

 

    1. 比较

访问者模式的优点:

(1)允许对组合结构加入新的操作,而无需改变结构本身

(2)加入新的操作相对容易

(3)访问者所进行的操作,代码是集中在一起的

用途和缺点:

(1)采用访问者模式会打破组合类的封装

(2)游走的功能牵涉其中,对组合结构的改变更加困难

 

  1. 总结

设计模式可分为:创建型、结构型、行为型

创建型模式:工厂模式(简单工厂、抽象工厂、工厂)、单例模式、建造者模式、原型模式

创建型模式的目的是创建实例

结构型模式:代理模式、适配器模式(默认适配、对象适配、类适配)、桥接模式、装饰模式、外观模式、享元模式

行为型模式:策略模式、观察者模式、责任链模式、模板方法模式、状态模式、备忘录模式、命令模式