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.Cache
The interface defines the necessary functionality (corresponding to the Component), among which, exceptorg.apache.ibatis.cache.impl.PerpetualCache
Everything 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