This is the second day of my participation in the August More text Challenge. For details, see:August is more challenging

Basic concept

  • Component: The Component interface that defines the behavior of all Component implementation classes and all decorators
  • ConcreteComponent: ConcreteComponent implementation class
  • Decorator: An abstract class that implements Component and encapsulates a Component object internally to facilitate composition and reuse
  • ConcreteDecorator: ConcreteDecorator implements a class that enhances some functionality.

advantages

  • Strong flexibility and scalability, through the dynamic combination of decorators, to achieve different requirements
  • To add a new requirement, add a decorator

disadvantages

  • Once there are many new requirements, it is difficult to maintain if there are nested decorators with multiple layers

Code sample

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

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

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

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

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

    private void doOtherThing(a){
        System.out.println("im shout"); }}Copy the code

Application in Mybatis

In Mybatis, the Decorator is omitted and the implementation class does the work directly.

Inside thisorg.apache.ibatis.cache.CacheThe interface defines the necessary functionality (corresponding to the Component), among which, exceptorg.apache.ibatis.cache.impl.PerpetualCacheEverything else is basically a ConcreteDecorator class.

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(a) {
    return id;
  }

  @Override
  public int getSize(a) {
    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(a) {
    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(! (oinstanceof Cache)) {
      return false;
    }

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

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

Everything else is roughly the same, just pick a random example

public class WeakCache implements Cache {
  // Strong reference collections to avoid garbage collection
  private final Deque<Object> hardLinksToAvoidGarbageCollection;
  // The GC object is stored in this queue
  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(a) {
    return delegate.getId();
  }

  @Override
  public int getSize(a) {
    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) {
          // If it is used, it is saved using a strong reference set
          hardLinksToAvoidGarbageCollection.addFirst(result);
          if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) {
            // Delete the oldest one when fullhardLinksToAvoidGarbageCollection.removeLast(); }}}}return result;
  }

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

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

  // Delete the GC object
  private void removeGarbageCollectedItems(a) {
    WeakEntry sv;
    while((sv = (WeakEntry) queueOfGarbageCollectedEntries.poll()) ! =null) { delegate.removeObject(sv.key); }}// Inherit the weak reference and cache the object
  private static class WeakEntry extends WeakReference<Object> {
    private final Object key;
    // It will be added to the queue when GC is performed
    private WeakEntry(Object key, Object value, ReferenceQueue<Object> garbageCollectionQueue) {
      super(value, garbageCollectionQueue);
      this.key = key; }}}Copy the code