设计一个缓存--针对各种类型的缓存
- [1. 设计顶层接口](#1. 设计顶层接口)
- [2. 设计抽象类 -- AbstractCacheManager](#2. 设计抽象类 -- AbstractCacheManager)
- [3. 具体子类](#3. 具体子类)
-
- [3.1 -- AlertRuleItemExpCacheManager](#3.1 -- AlertRuleItemExpCacheManager)
- [3.2 -- AlertRuleItemSrcCacheManager](#3.2 -- AlertRuleItemSrcCacheManager)
- [4. 类图关系](#4. 类图关系)
1. 设计顶层接口
java
// 定义为一个泛型接口,提供给抽象类使用
public interface CacheManager<T> {
// 获取所有的缓存item
List<T> getAll();
// 根据条件获取某些缓存item
List<T> get(Predicate<T> predicate);
// 设置缓存
boolean set(T t);
// 设置缓存list
boolean set(List<T> tList);
}
有接口必定有实现类或者抽象类,实现接口。
那为了更好地控制子类的行为,可以做一个抽象类,控制子类行为。
- 分析:
- 抽象类作为缓存管理的话,那么就需要提供安全访问数据
- 需要考虑线程安全问题。
- 花絮: 不仅要满足上述需求,而且让代码尽量简洁。
2. 设计抽象类 -- AbstractCacheManager
- 属性设计:
- 需要一个缓存
- 需要一个线程安全机制方案
- 行为设计:
- 自己的行为:
- 利用线程安全机制控制缓存的读写。
- 权限:仅自己可访问
- 后代的行为:
- 访问一些简单api方法即可实现安全访问缓存
- 权限:公共访问
- 自己的行为:
- 设计模式:
- 包裹思想,将后代行为方法中,包裹一层安全访问的行为。
Java Code:
java
// properties design:
protected ConcurrentMap<String, T> cache;
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
// subclass to implements these abstract methods.
protected abstract List<T> getAllByCache();
protected abstract void setByCache(T t);
protected abstract void setByCache(List<T> tList);
protected abstract List<T> getByCache(Predicate<T> predicate);
// next content needs to consider safety of multithreads. following methods do implements.
// entry to use
@Override
public final List<T> getAll() {
return this.readLockThenGet(() -> this.getAllByCache());
}
@Override
public final List<T> get(Predicate<T> predicate) {
return this.readLockThenGet(pre -> getByCache(pre), predicate);
}
@Override
public final boolean set(T t) {
return this.writeLockThenSet((Consumer<T>) obj -> set(obj), t);
}
@Override
public final boolean set(List<T> tList) {
return this.writeLockThenSet((Consumer<List<T>>) list -> set(list), tList);
}
// current abstract class access cache object.
private boolean writeLockThenSet(Consumer consumer, Object object){
boolean wLock = false;
try {
if (!(wLock = lock.writeLock().tryLock(100, TimeUnit.MICROSECONDS))) {
return false;
}
consumer.accept(object);
return true;
} catch (Exception e) {
return false;
} finally {
if(wLock) {
lock.writeLock().unlock();
}
}
}
private List<T> readLockThenGet(Supplier<List<T>> supplier){
boolean rLock = false;
try{
if(!(rLock = lock.readLock().tryLock(100, TimeUnit.MICROSECONDS))){
return null;
}
return supplier.get();
}catch (Exception e){
return null;
}finally {
if(rLock) {
lock.readLock().unlock();
}
}
}
private List<T> readLockThenGet(Function<Predicate<T>, List<T>> function, Predicate<T> predicate){
boolean rLock = false;
try{
if(!(rLock = lock.readLock().tryLock(100, TimeUnit.MICROSECONDS))){
return null;
}
return function.apply(predicate);
}catch (Exception e){
return null;
}finally {
if(rLock) {
lock.readLock().unlock();
}
}
}
3. 具体子类
3.1 -- AlertRuleItemExpCacheManager
java
@Component("alertRuleItemExpCacheManager")
public class AlertRuleItemExpCacheManager<T extends AlertRuleItemExpCache> extends AbstractCacheManager<AlertRuleItemExpCache> {
@Resource
private AlertRuleItemExpDao alertRuleItemExpDao;
@Override
protected List<AlertRuleItemExpCache> getAllByCache() {
if (null == cache) {
List<AlertRuleItemExp> alertRuleItemSrcList =
alertRuleItemExpDao.selectList(Wrappers.<AlertRuleItemExp>lambdaQuery().eq(AlertRuleItemExp::getDeleted, 0));
cache = alertRuleItemSrcList.stream().map(entity -> entity.toCache())
.collect(Collectors.toConcurrentMap(cache -> cache.getId().toString(), cache -> cache));
}
return cache.values().stream()
.sorted(Comparator.comparing(AlertRuleItemExpCache::getId))
.collect(Collectors.toList());
}
@Override
protected void setByCache(AlertRuleItemExpCache alertRuleItemExpCache) {
cache.put(alertRuleItemExpCache.getId().toString(), alertRuleItemExpCache);
}
@Override
protected void setByCache(List<AlertRuleItemExpCache> alertRuleItemExpCacheList) {
alertRuleItemExpCacheList.parallelStream().forEach(alertRuleItemExpCache ->
cache.put(alertRuleItemExpCache.getId().toString(), alertRuleItemExpCache));
}
@Override
protected List<AlertRuleItemExpCache> getByCache(Predicate<AlertRuleItemExpCache> predicate) {
return getAllByCache().stream().filter(cache -> predicate.test(cache)).collect(Collectors.toList());
}
}
3.2 -- AlertRuleItemSrcCacheManager
java
@Component("alertRuleItemSrcCacheManager")
public class AlertRuleItemSrcCacheManager<T extends AlertRuleItemSrcCache> extends AbstractCacheManager<AlertRuleItemSrcCache> {
@Resource
private AlertRuleItemSrcDao alertRuleItemSrcDao;
@Override
protected List<AlertRuleItemSrcCache> getAllByCache() {
if (null == cache) {
List<AlertRuleItemSrc> alertRuleItemSrcList =
alertRuleItemSrcDao.selectList(Wrappers.<AlertRuleItemSrc>lambdaQuery().eq(AlertRuleItemSrc::getDeleted, 0));
cache = alertRuleItemSrcList.stream().map(entity -> entity.toCache())
.collect(Collectors.toConcurrentMap(cache -> cache.getId().toString(), cache -> cache));
}
return cache.values().stream()
.sorted(Comparator.comparing(AlertRuleItemSrcCache::getId))
.collect(Collectors.toList());
}
@Override
protected void setByCache(AlertRuleItemSrcCache alertRuleItemSrcCache) {
cache.put(alertRuleItemSrcCache.getId().toString(), alertRuleItemSrcCache);
}
@Override
protected void setByCache(List<AlertRuleItemSrcCache> alertRuleItemSrcCacheList) {
alertRuleItemSrcCacheList.parallelStream().forEach(alertRuleItemSrcCache ->
cache.put(alertRuleItemSrcCache.getId().toString(), alertRuleItemSrcCache));
}
@Override
protected List<AlertRuleItemSrcCache> getByCache(Predicate<AlertRuleItemSrcCache> predicate) {
return getAllByCache().stream().filter(cache -> predicate.test(cache)).collect(Collectors.toList());
}
}