结合Mybatis源码学习装饰器模式

473 阅读2分钟

这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战

基础概念

image.png

  • Component:组件接口,定义了全部组件实现类以及所有装饰器实现的行为
  • ConcreteComponent:具体组件实现类)
  • Decorator:装饰器,实现了Component的抽象类,内部封装了一个Component对象,方便组合及复用
  • ConcreteDecorator:具体装饰器实现类,对某些功能进行增强。

优点

  • 灵活性和可扩展性较强,通过装饰器的动态组合,实现不同的需求
  • 添加新需求,添加装饰器即可

缺点

  • 新需求一旦很多,如果出现嵌套多层的装饰器,就很难维护

代码示例

  • Component&ConcreteComponent
//Component
public interface Animal {
    void run();
}
//ConcreteComponent
public class People implements Animal {
    @Override
    public void run() {
        System.out.println("people run");
    }
}
//ConcreteComponent
public class Tiger implements Animal{

    @Override
    public void run() {
        System.out.println("tiger run");
    }
}
  • Decorator
//Decorator
public abstract class AnimalDecorator implements Animal {
    protected Animal decoratorAnimal;

    public AnimalDecorator(Animal decoratorAnimal){
        this.decoratorAnimal=decoratorAnimal;
    }

    @Override
    public void run(){
        decoratorAnimal.run();
    }
}
  • ConcreteDecorator
public class AllAnimalDecorator extends AnimalDecorator {

    public AllAnimalDecorator(Animal decoratorAnimal) {
        super(decoratorAnimal);
    }
    @Override
    public void run(){
        decoratorAnimal.run();
        doOtherThing();
    }

    private void doOtherThing(){
        System.out.println("im shout");
    }
}

Mybatis中的应用

image.png Mybatis中则是省去了Decorator,直接由实现类完成。

image.png 这里面org.apache.ibatis.cache.Cache接口定义了必要的功能(对应Component),其中,除了org.apache.ibatis.cache.impl.PerpetualCache其他基本上都可以看作是装饰器实现类(ConcreteDecorator)。

public class PerpetualCache implements Cache {

  private final String id;

  private final Map<Object, Object> cache = new HashMap<>();

  public PerpetualCache(String id) {
    this.id = id;
  }

  @Override
  public String getId() {
    return id;
  }

  @Override
  public int getSize() {
    return cache.size();
  }

  @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);
  }

  @Override
  public void clear() {
    cache.clear();
  }

  @Override
  public boolean equals(Object o) {
    if (getId() == null) {
      throw new CacheException("Cache instances require an ID.");
    }
    if (this == o) {
      return true;
    }
    if (!(o instanceof Cache)) {
      return false;
    }

    Cache otherCache = (Cache) o;
    return getId().equals(otherCache.getId());
  }

  @Override
  public int hashCode() {
    if (getId() == null) {
      throw new CacheException("Cache instances require an ID.");
    }
    return getId().hashCode();
  }

}

其他都大体相同,随便挑一个举例

public class WeakCache implements Cache {
  //强引用集合,避免垃圾回收
  private final Deque<Object> hardLinksToAvoidGarbageCollection;
  //被GC的对象保存进这个队列中
  private final ReferenceQueue<Object> queueOfGarbageCollectedEntries;
  private final Cache delegate;
  private int numberOfHardLinks;

  public WeakCache(Cache delegate) {
    this.delegate = delegate;
    this.numberOfHardLinks = 256;
    this.hardLinksToAvoidGarbageCollection = new LinkedList<>();
    this.queueOfGarbageCollectedEntries = new ReferenceQueue<>();
  }

  @Override
  public String getId() {
    return delegate.getId();
  }

  @Override
  public int getSize() {
    removeGarbageCollectedItems();
    return delegate.getSize();
  }

  public void setSize(int size) {
    this.numberOfHardLinks = size;
  }

  @Override
  public void putObject(Object key, Object value) {
    removeGarbageCollectedItems();
    delegate.putObject(key, new WeakEntry(key, value, queueOfGarbageCollectedEntries));
  }

  @Override
  public Object getObject(Object key) {
    Object result = null;
    @SuppressWarnings("unchecked") // assumed delegate cache is totally managed by this cache
    WeakReference<Object> weakReference = (WeakReference<Object>) delegate.getObject(key);
    if (weakReference != null) {
      result = weakReference.get();
      if (result == null) {
        delegate.removeObject(key);
      } else {
        synchronized (hardLinksToAvoidGarbageCollection) {
          //如果用到了就使用强引用集合保存下来
          hardLinksToAvoidGarbageCollection.addFirst(result);
          if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) {
            //满了删除最老的
            hardLinksToAvoidGarbageCollection.removeLast();
          }
        }
      }
    }
    return result;
  }

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

  @Override
  public void clear() {
    synchronized (hardLinksToAvoidGarbageCollection) {
      hardLinksToAvoidGarbageCollection.clear();
    }
    removeGarbageCollectedItems();
    delegate.clear();
  }

  //删除被GC的对象
  private void removeGarbageCollectedItems() {
    WeakEntry sv;
    while ((sv = (WeakEntry) queueOfGarbageCollectedEntries.poll()) != null) {
      delegate.removeObject(sv.key);
    }
  }
    //继承弱引用,缓存的是这个对象
  private static class WeakEntry extends WeakReference<Object> {
    private final Object key;
    //GC的时候会添加进队列中
    private WeakEntry(Object key, Object value, ReferenceQueue<Object> garbageCollectionQueue) {
      super(value, garbageCollectionQueue);
      this.key = key;
    }
  }

}