Двухуровневый кэш со стратегией

 
 
 
Сообщения:10
Задача: двухуровневый кэш (1 - оперативная память, 2 - файл).
Входные параметры - размер кэша в оперативной памяти, размер файлового кэша, стратегия кэширования.
Ход мыслей был такой.

1) Определение желаемого интерфейса кэша вообще:
public abstract interface Cache<K, V> {

    public abstract void put(K key, V value);
    public abstract V get(K key) throws NotFoundException;
    public abstract V remove(K key) throws NotFoundException;
    public abstract void clear();
    public abstract int size();
}


2) Реализация кэширования в оперативной памяти и файлах без привязки к определенной стратегии кэширования (размер кэша не задается, пользователь может добавлять/удалять элементы в кэш без ограничений):
public class InMemoryCache<K, V>
        implements Cache<K, V> { ... }

public class InFileCache<K extends Serializable, V extends Serializable>
        implements Cache<K, V> { 
		
		private final String cacheDirectoryPath;
    
		public InFileCache() {			
			this(DEFAULT_CACHE_DIRECTORY_PATH);
		}
            
		public InFileCache(String cacheDirectoryPath) { ... }
		
		...
}


3) Определение стратегии кэширования:
public abstract class Strategy<K, D> {

    protected Map<K, D> useInfoMap = new HashMap();
    
    /**
     * Determines key of object to remove. Algorithm is defined by concrete 
     * strategy realization. Return null if it is no objects in cache.
     * @return key of object to remove
     */
    public K getKeyToRemove() {
        D keyDataToRemove = getKeyDataToRemove();

        for (Map.Entry e : this.useInfoMap.entrySet()) {
            if (((D) e.getValue()).equals(keyDataToRemove)) {
                return (K)e.getKey();
            }
        }

		// FIX ME.
        return null;
    }
    
    protected abstract D getKeyDataToRemove();

    public void setKeyData(K key) {
        setKeyData(key, getDefaultKeyData());
    }    
    
    protected abstract D getDefaultKeyData();    

    public void setKeyData(K key, D data) {
        useInfoMap.put(key, data);
    }
    
    public void clear() {
        useInfoMap.clear();
    }
    
    public void remove(K key) {
        useInfoMap.remove(key);
    }
    
    public D getKeyData(K key) {
        return useInfoMap.get(key);
    }
}


4) Реализация стратегий кэширования:
public class LruStrategy<K> extends Strategy<K, Date>{
  
    @Override
    protected Date getKeyDataToRemove() {
        return (Date) Collections.min(this.useInfoMap.values());
    }

    @Override
    protected Date getDefaultKeyData() {
        return new Date();
    }
}


5) Определение кэша со стратегией (с использованием шаблона Стратегия):
public class StrategyCache<K, V, D> implements Cache<K, V> {

    private final Strategy<K, D> strategy;
    private final Cache cache;
    
    private final int capacity;
    
    public enum Type {
        LRU_STRATEGY;
		...
    }
    
    public StrategyCache(Cache cache, int capacity) {
        
        this(cache, capacity, Type.LRU_STRATEGY);
    }
    
    public StrategyCache(Cache cache, int capacity, Type type) {
        this.cache = cache;
        this.capacity = capacity;
        switch (type) {
            case LRU_STRATEGY:
                this.strategy = new LruStrategy();
			...
        }
    }		
	
	...
}


6) Собственно, реализация двухуровневого кэша:
public class TwoLevelCache<K, V extends Serializable, D> implements Cache<K, V> {

    private final StrategyCache<K, V, D> inMemoryCache;
    private final StrategyCache<K, V, D> inFileCache;
    
    public TwoLevelCache(int inMemoryCacheCapacity, int inFileCacheCapacity, StrategyCache.Type cacheStrategy) {
        this.inMemoryCache = new StrategyCache(new InMemoryCache(), inMemoryCacheCapacity, cacheStrategy);
        this.inFileCache = new StrategyCache(new InFileCache(), inFileCacheCapacity, cacheStrategy);
    }
	...
}


Здесь возник затык, т.к. при указанной реализации получается, что для задания параметра для InFileCache (cacheDirectoryPath) нужно добавлять еще один параметр в конструктор TwoLevelCache.
Есть какие-либо другие варианты? Буду очень благодарна за любую помощь, т.к. сейчас вообще нет понимания, в какую сторону копать...
 
 
Сообщения:86
Если TwoLevelCache не в состоянии определить эти параметры самостоятельно, то как ни крути, клиенту всеравно придется передать их. Можно перенести создание объектов на клиента, для удобства предоставив фабрики (Factory) с выразительными именами. Правда при этом раскрывается внутренняя структура TwoLevelCache (хотя это не всегда плохо). Либо сделать builder'a для TwoLevelCache.
P.S. Map.Entry является генериком, а использован как raw.
 
 
Сообщения:10
Flashrunner, спасибо большое! Вроде разобралась.
И за генерики спасибо:)
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет