您现在的位置是:网站首页 > 缓存策略与设计模式的结合文章详情
缓存策略与设计模式的结合
陈川
【
JavaScript
】
39416人已围观
9459字
缓存策略与设计模式的结合
缓存策略与设计模式的结合能够显著提升应用性能与代码可维护性。通过合理运用设计模式,可以优雅地实现缓存逻辑,减少重复计算和网络请求,同时保持代码的清晰与扩展性。
代理模式实现缓存控制
代理模式是缓存场景中最直接的设计模式应用。通过创建代理对象拦截原始操作,可以在访问真实对象前先检查缓存。例如实现一个图片加载代理:
class ImageLoader {
load(url) {
console.log(`Loading image from ${url}`);
return `Image data from ${url}`;
}
}
class ImageLoaderProxy {
constructor() {
this.cache = new Map();
this.loader = new ImageLoader();
}
load(url) {
if (this.cache.has(url)) {
console.log(`Returning cached image for ${url}`);
return this.cache.get(url);
}
const imageData = this.loader.load(url);
this.cache.set(url, imageData);
return imageData;
}
}
// 使用示例
const proxy = new ImageLoaderProxy();
proxy.load('photo1.jpg'); // 真实加载
proxy.load('photo1.jpg'); // 返回缓存
这种模式特别适合处理代价高昂的操作,如网络请求、复杂计算等。代理对象完全控制了对原始对象的访问,可以灵活添加各种缓存策略。
策略模式实现可替换缓存算法
策略模式允许在运行时选择不同的缓存淘汰算法。以下是实现LRU和FIFO两种策略的示例:
// 策略接口
class CacheStrategy {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
}
get(key) {}
put(key, value) {}
}
// LRU策略
class LRUStrategy extends CacheStrategy {
get(key) {
if (!this.cache.has(key)) return null;
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
put(key, value) {
if (this.cache.has(key)) this.cache.delete(key);
if (this.cache.size >= this.capacity) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
}
// FIFO策略
class FIFOStrategy extends CacheStrategy {
get(key) {
return this.cache.get(key) || null;
}
put(key, value) {
if (this.cache.size >= this.capacity) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
}
// 缓存上下文
class CacheContext {
constructor(strategy) {
this.strategy = strategy;
}
get(key) {
return this.strategy.get(key);
}
put(key, value) {
this.strategy.put(key, value);
}
setStrategy(strategy) {
this.strategy = strategy;
}
}
// 使用示例
const lruCache = new CacheContext(new LRUStrategy(2));
lruCache.put('a', 1);
lruCache.put('b', 2);
lruCache.get('a'); // 访问a使其成为最近使用
lruCache.put('c', 3); // 淘汰b而不是a
const fifoCache = new CacheContext(new FIFOStrategy(2));
fifoCache.put('a', 1);
fifoCache.put('b', 2);
fifoCache.get('a'); // 访问不影响淘汰顺序
fifoCache.put('c', 3); // 淘汰a
策略模式使得缓存算法可以独立变化,新增策略时不需要修改现有代码,符合开闭原则。
装饰器模式增强缓存功能
装饰器模式可以在不修改原有对象的情况下动态添加缓存功能。以下是使用ES7装饰器语法的示例:
function cacheDecorator(target, name, descriptor) {
const originalMethod = descriptor.value;
const cache = new Map();
descriptor.value = function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
console.log('Returning cached result');
return cache.get(key);
}
const result = originalMethod.apply(this, args);
cache.set(key, result);
return result;
};
return descriptor;
}
class Calculator {
@cacheDecorator
factorial(n) {
console.log('Calculating factorial for', n);
return n <= 1 ? 1 : n * this.factorial(n - 1);
}
}
// 使用示例
const calc = new Calculator();
calc.factorial(5); // 计算并缓存所有中间结果
calc.factorial(5); // 直接从缓存返回
装饰器模式特别适合为已有方法添加缓存功能,保持原有代码不变的同时获得性能提升。这种方法在React组件计算属性时特别有用。
工厂模式创建缓存实例
工厂模式可以封装缓存对象的创建过程,根据不同的参数返回不同类型的缓存实例:
class MemoryCache {
constructor() {
this.store = new Map();
}
get(key) { return this.store.get(key); }
set(key, value) { this.store.set(key, value); }
}
class SessionStorageCache {
get(key) { return JSON.parse(sessionStorage.getItem(key)); }
set(key, value) { sessionStorage.setItem(key, JSON.stringify(value)); }
}
class CacheFactory {
static create(type) {
switch(type) {
case 'memory':
return new MemoryCache();
case 'session':
return new SessionStorageCache();
default:
throw new Error('Unknown cache type');
}
}
}
// 使用示例
const memoryCache = CacheFactory.create('memory');
memoryCache.set('temp', {a: 1});
const sessionCache = CacheFactory.create('session');
sessionCache.set('user', {name: 'John'});
工厂模式使得缓存实现细节对客户端代码透明,可以轻松切换不同的存储后端而无需修改业务逻辑。
观察者模式实现缓存失效
观察者模式可以用于实现缓存失效机制,当数据发生变化时自动更新相关缓存:
class CacheObserver {
constructor() {
this.subscribers = new Map();
}
subscribe(key, callback) {
if (!this.subscribers.has(key)) {
this.subscribers.set(key, []);
}
this.subscribers.get(key).push(callback);
}
notify(key) {
if (this.subscribers.has(key)) {
this.subscribers.get(key).forEach(cb => cb());
}
}
}
class DataService {
constructor() {
this.cache = new Map();
this.observer = new CacheObserver();
}
getData(key) {
if (this.cache.has(key)) {
return Promise.resolve(this.cache.get(key));
}
return this.fetchData(key).then(data => {
this.cache.set(key, data);
return data;
});
}
updateData(key, newData) {
return this.saveData(key, newData).then(() => {
this.cache.delete(key);
this.observer.notify(key);
return newData;
});
}
fetchData(key) { /* 模拟网络请求 */ }
saveData(key, data) { /* 模拟保存操作 */ }
}
// 使用示例
const service = new DataService();
// 组件A订阅数据更新
service.observer.subscribe('userData', () => {
console.log('User data updated, refreshing...');
service.getData('userData').then(/* 更新UI */);
});
// 更新数据会触发所有订阅者
service.updateData('userData', {name: 'Alice'});
这种模式在需要保持缓存与数据源同步的场景中非常有效,特别是当多个组件依赖同一份数据时。
单例模式管理全局缓存
单例模式确保整个应用使用同一个缓存实例,避免重复创建和状态不一致:
class GlobalCache {
constructor() {
if (!GlobalCache.instance) {
this._cache = new Map();
GlobalCache.instance = this;
}
return GlobalCache.instance;
}
get(key) {
return this._cache.get(key);
}
set(key, value) {
this._cache.set(key, value);
}
clear() {
this._cache.clear();
}
}
// 使用示例
const cache1 = new GlobalCache();
cache1.set('theme', 'dark');
const cache2 = new GlobalCache();
console.log(cache2.get('theme')); // 'dark'
// 两个变量引用同一个实例
console.log(cache1 === cache2); // true
单例缓存特别适合存储应用全局状态,如用户偏好、主题设置等。在React应用中,可以结合Context API实现类似的全局状态管理。
组合模式实现多级缓存
组合模式可以构建多级缓存系统,形成缓存层次结构:
class CacheComponent {
get(key) {}
set(key, value) {}
}
class MemoryCache extends CacheComponent {
constructor() {
super();
this.store = new Map();
}
get(key) {
return this.store.get(key);
}
set(key, value) {
this.store.set(key, value);
}
}
class DiskCache extends CacheComponent {
get(key) {
return localStorage.getItem(key);
}
set(key, value) {
localStorage.setItem(key, value);
}
}
class MultiLevelCache extends CacheComponent {
constructor() {
super();
this.caches = [];
}
addCache(cache) {
this.caches.push(cache);
}
get(key) {
for (const cache of this.caches) {
const value = cache.get(key);
if (value !== undefined && value !== null) {
// 填充上层缓存
for (const upperCache of this.caches.slice(0, this.caches.indexOf(cache))) {
upperCache.set(key, value);
}
return value;
}
}
return null;
}
set(key, value) {
this.caches.forEach(cache => cache.set(key, value));
}
}
// 使用示例
const multiCache = new MultiLevelCache();
multiCache.addCache(new MemoryCache()); // 第一级:内存缓存
multiCache.addCache(new DiskCache()); // 第二级:本地存储
multiCache.set('token', 'abc123');
console.log(multiCache.get('token')); // 从内存获取
localStorage.removeItem('token'); // 模拟磁盘缓存失效
console.log(multiCache.get('token')); // 依然可以从内存获取
多级缓存系统结合了不同存储介质的优势,内存缓存提供快速访问,持久化缓存保证数据不丢失。这种模式在实现类似CPU缓存架构时特别有效。
状态模式实现缓存生命周期管理
状态模式可以管理缓存对象的不同生命周期状态:
class CacheState {
constructor(cache) {
this.cache = cache;
}
get(key) {}
put(key, value) {}
clear() {}
}
class ActiveState extends CacheState {
get(key) {
return this.cache.data.get(key) || null;
}
put(key, value) {
this.cache.data.set(key, value);
if (this.cache.data.size >= this.cache.limit) {
this.cache.setState(new FullState(this.cache));
}
}
clear() {
this.cache.data.clear();
}
}
class FullState extends CacheState {
get(key) {
const value = this.cache.data.get(key);
if (!value) return null;
// 访问后移动到MRU位置
this.cache.data.delete(key);
this.cache.data.set(key, value);
return value;
}
put(key, value) {
// 淘汰最久未使用的条目
const firstKey = this.cache.data.keys().next().value;
this.cache.data.delete(firstKey);
this.cache.data.set(key, value);
}
clear() {
this.cache.data.clear();
this.cache.setState(new ActiveState(this.cache));
}
}
class SmartCache {
constructor(limit = 10) {
this.limit = limit;
this.data = new Map();
this.setState(new ActiveState(this));
}
setState(state) {
this.state = state;
}
get(key) {
return this.state.get(key);
}
put(key, value) {
this.state.put(key, value);
}
clear() {
this.state.clear();
}
}
// 使用示例
const cache = new SmartCache(2);
cache.put('a', 1); // ActiveState
cache.put('b', 2); // ActiveState
cache.put('c', 3); // 切换到FullState,淘汰a
console.log(cache.get('a')); // null
console.log(cache.get('b')); // 2,b变为MRU
cache.put('d', 4); // 淘汰c而不是b
状态模式使得缓存可以根据当前状态改变行为,每个状态类专注于特定状态下的逻辑,使代码更加清晰。
上一篇: 懒加载与预加载的模式选择
下一篇: 算法复杂度与设计模式的关系