装饰器模式

1. 装饰器模式简介

装饰器模式实现了将复杂的功能切分成一个个独立的装饰器,通过多个独立装饰器的动态组合,形成所需的功能组件,以满足相应的需求。它的类图如下:



装饰器模式的角色:

  • 组件接口(Component):定义了所有具体组件和装饰器的行为。
  • 具体组件类(Concrete Component):通常情况下,具体组件类就是被装饰器装饰的原始对象,它提供了最基本的功能,其他高级功能都是通过装饰器类添加到该类之上的。
  • 装饰器(Decorator):所有具体装饰器类的父类,它封装了一个具体组件类的对象,即被装饰的对象。装饰器仅是装饰效果,所有装饰器最终都会调用具体组件类对象的相应方法。
  • 具体装饰器类(Concrete Decorator):一个具体装饰器类对应一个独立的功能。

2. MyBatis中的装饰器模式

MyBatis中的(仅列出组件接口)Cache、Executor等都用到了装饰器模式,这里以Cache为例进行介绍,Cache及其实现使用了装饰器模式的变体,舍去了Decorator抽象类,类图如下:


2.1 Cache
// 扮演着组件接口的角色
public interface Cache {

 // 下面定义了缓存相关的操作
  void putObject(Object key, Object value);
  Object getObject(Object key);
  Object removeObject(Object key);

  // 其余方法(略)

}
2.2 PerpetualCache
// 扮演着具体组件类的角色
public class PerpetualCache implements Cache {

  // 该缓存对象的id
  private final String id; 

  // 用于记录缓存项
  private Map cache = new HashMap<>();

  // 注意构造方法的参数类型,具体装饰器类的构造方法参数都是Cache类型
  public PerpetualCache(String id) {
    this.id = id;
  }

  @Override
  public void putObject(Object key, Object value) {
    cache.put(key, value);
  }

  @Override
  public Object getObject(Object key) {
    return cache.get(key);
  }

  @Override
  public Object removeObject(Object key) {
    return cache.remove(key);
  }

  // 其余方法(略)

}
2.3 具体装饰器类

Cache的具体装饰器类很多,每个装饰器类都对应一个独立的功能,如ScheduledCache提供了周期性清理功能、LoggingCache提供了日志功能、SynchronizedCache提供了同步功能、SerializedCache 提供了序列化功能,下面仅就SynchronizedCache进行说明:

// 扮演着具体装饰器类的角色
public class SynchronizedCache implements Cache {

  // 底层Cache对象(可能是具体装饰器类,也可能是具体组件类)
  private final Cache delegate;
  
  // 注意构造方法的参数类型
  public SynchronizedCache(Cache delegate) {
    this.delegate = delegate;
  }

  // 缓存相关的方法都加了synchronized关键字来进行同步
  @Override
  public synchronized void putObject(Object key, Object object) {
    delegate.putObject(key, object);
  }

  @Override
  public synchronized Object getObject(Object key) {
    return delegate.getObject(key);
  }

  @Override
  public synchronized Object removeObject(Object key) {
    return delegate.removeObject(key);
  }

  // 其他方法(略)

}

3. 总结

装饰器模式明显的优点就是将复杂功能切分为独立的装饰器,通过多个装饰器的动态组合来实现特定的功能。在需要新功能时,只需添加新的具体装饰器类,在配置文件中添加相应的配置,即可被MyBatis使用,符合开闭原则。
通过继承也可以实现功能的扩展,但存在很多缺点。例如,若有4个待添加的功能,组合出所有功能就需要(4+6+4+1=)15个子类,且有些被final修饰的类是不能被继承的。装饰器模式体现了:组合优于继承。

你可能感兴趣的:(装饰器模式)