设计模式学习(三) — 结构型模式
结构型模式主要是侧重于类之间结构构建的设计经验总结
个人主页:tuzhenyu’s page
原文地址:设计模式学习(三) — 结构型模式
(0) 基本概念
结构型设计模式侧重于类之间的结构构建,用来解决模块之间的耦合问题;
结构型设计模式主要包括装饰器模式,适配器模式,代理模式等;
(1) 装饰器模式
装饰器模式是动态地给一个对象添加一些额外的功能,把核心功能和装饰功能区分开来更好的控制对象功能;
装饰器功能的好处:
将特定的装饰功能封装到一个类中用于包装核心功能的类,这样可以有选择有顺序的定制特定功能的对象;
将核心功能和装饰功能区分开来,去除相关类中重复的装饰逻辑,同时也降低核心功能和装饰功能的耦合度;
Mybatis中的装饰器模式
- 在MyBatis中具体的SQL命令执行是通过Executor完成的,如果在配置文件转中开启Cache缓存功能则在生成Executor实例时通过装饰器模式将Executor核心类包装成CachingExecutor增加缓存功能;
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null?this.defaultExecutorType:executorType;
executorType = executorType == null?ExecutorType.SIMPLE:executorType;
Object executor;
if(ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if(ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
//装饰器模式添加缓存功能
if(this.cacheEnabled) {
executor = new CachingExecutor((Executor)executor);
}
Executor executor1 = (Executor)this.interceptorChain.pluginAll(executor);
return executor1;
}
- 带有缓存功能的执行类CachingExecutor在执行具体的SQL指令时会执行装饰逻辑同时也会将指令转发给核心执行类SimpleExecutor;
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
flushCacheIfRequired(ms);
return delegate.update(ms, parameterObject);
}
Collectios中的装饰器模式
Collections工具类中将普通集合类转化成线程安全的集合类是通过装饰器模式,比如Collections.synchronizedList(),Collections.synchronizedMap()等;
调用Collections工具类方法创建装饰器类,功能的实现仍是通过传入的参数普通集合类只是在方法外加上一层synchronized锁;
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
Java IO中的装饰器模式
- BufferedInputStream,DataInputStream等都是在原始数据流基础上添加新的功能,BufferedInputStream用来从硬盘将数据读入到一个内存缓冲区中,并从缓冲区提供数据;DataInputStream提供基于多字节的读取方法,可以读取原始类型的数据。
(2) 适配器模式
适配器模式是将一个类的接口转换成期望类的接口,让原本不兼容的类可以一起工作
适配器模式的主要优点是将目标类和适配者类解耦,增加了类的透明性和复用性,同时系统的灵活性和扩展性都非常好,更换适配器或者增加新的适配器都非常方便
Java IO中的适配器模式
- ByteArrayInputStream是Java IO中适配器模式的使用,将内存中的数组转化成数据流从而能够进行流处理
try
{
DataInputStream in = new DataInputStream(new ByteArrayInputStream(BufferedInputFile.read("MemoryInput.java").getBytes()));
while(true)
{
System.out.print((char)in.readByte());
}
}
catch (EOFException e)
{
System.err.println("End Of Stream");
}
(3) 代理模式
给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原对象,而是通过代理对象间接地操控原对象。
代理模式和装饰器模式区别:代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。并且,当我们使用装饰器模 式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。
代理模式的使用情景
Spring中AOP功能的实现核心就是动态代理,在装载Bean时根据配置文件判断是否生成相应的代理类实例;
RPC中通过代理模式是对底层远程调用过程进行隐藏,使客户端调用方法时和调用普通方法一样;
总结
结构型设计模式主要是在特定情况下对类与类之间的结构进行构建,根据具体的情况可以单独使用或者组合使用装饰器模式,适配器模式,代理模式等;