您现在的位置是:网站首页 > 缓存策略与设计模式的结合文章详情

缓存策略与设计模式的结合

缓存策略与设计模式的结合

缓存策略与设计模式的结合能够显著提升应用性能与代码可维护性。通过合理运用设计模式,可以优雅地实现缓存逻辑,减少重复计算和网络请求,同时保持代码的清晰与扩展性。

代理模式实现缓存控制

代理模式是缓存场景中最直接的设计模式应用。通过创建代理对象拦截原始操作,可以在访问真实对象前先检查缓存。例如实现一个图片加载代理:

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

状态模式使得缓存可以根据当前状态改变行为,每个状态类专注于特定状态下的逻辑,使代码更加清晰。

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步