在课堂中实施单一职责原则(SRP)

时间:2019-05-28 01:48:28

标签: javascript

我想重构Cache类,以便它不违反单一职责原则(SRP)。

但是,我很难确定如何将Cache类中不必要的步骤重构为memoize函数。理想情况下,我在Cachegetset

中有两个方法
function isObject(arg) {
  const typeOfObj = typeof arg;
  return (typeOfObj === 'object' || typeOfObj === 'function') && arg !== null;
}

class Cache {
  constructor() {
    this.map = new Map();
    this.weakmap = new WeakMap();
  }

  // create or retrieve a nested Cache instance based on an arguments object
  get(args) {
    let cache = this;

    for (const key of args) {
      const map = cache[isObject(key) ? 'weakmap' : 'map'];
      cache = map.get(key) || map.set(key, new Cache()).get(key);
    }

    return cache;
  }
}

function memoize(fn) {
  const cache = new Cache();

  return (...args) => {
    // get (or create) a cache item

    const item = cache.get(args);
    if (Reflect.has(item, 'value')) {
      return item.value;
    }
    return (item.value = fn(args));
  };
}

let counter = 1;
function foo() {
  counter += 1;
  return counter;
}

const id1 = Symbol('id');
const id2 = Symbol('id');
const obj1 = { a: 1 };
const obj2 = { a: 1 };

const memoizedFoo = memoize(foo);
console.log(memoizedFoo(id1)); // 2
console.log(memoizedFoo(id1)); // 2
console.log(memoizedFoo(id2)); // 3
console.log(memoizedFoo(id2)); // 3
console.log(memoizedFoo(obj1)); // 4
console.log(memoizedFoo(obj1)); // 4
console.log(memoizedFoo(obj2)); // 5
console.log(memoizedFoo(obj2)); // 5
console.log(memoizedFoo(5)); // 6
console.log(memoizedFoo(5)); // 6
console.log(memoizedFoo(4)); // 7
console.log(memoizedFoo(4)); // 7

1 个答案:

答案 0 :(得分:2)

一种选择是在NestedCache类上具有3个方法:

  • getNestedMap,在给定键数组的情况下迭代地图
  • getMap,以获取特定Map中某个键的值
  • setKeyIfNeeded,用于为Map的键设置值(如果尚不存在)

如果需要,您可以使用reduce遍历键数组,而不是不断地重新分配cache变量,以提高功能。

function isObject(arg) {
  const typeOfObj = typeof arg;
  return (typeOfObj === 'object' || typeOfObj === 'function') && arg !== null;
}

class NestedCache {
  constructor() {
    this.map = new Map();
    this.weakmap = new WeakMap();
  }

  // retrieve a nested Cache instance based on an array of keys
  getNestedMap(keys) {
    return keys.reduce((cache, key) => cache.getMap(key), this);
  }
  // return a Cache's value at a key
  getMap(key) {
    const map = this[isObject(key) ? 'weakmap' : 'map'];
    this.setKeyIfNeeded(map, key);
    return map.get(key);
  }
  // create a Cache's key, if needed
  setKeyIfNeeded(map, key) {
    if (!map.has(key)) {
      map.set(key, new NestedCache());
    }
  }
}

function memoize(fn) {
  const cache = new NestedCache();

  return (...args) => {
    // get (or create) a cache item
    const item = cache.getNestedMap(args);
    if (Reflect.has(item, 'value')) {
      return item.value;
    }
    return (item.value = fn(args));
  };
}

let counter = 1;
function foo() {
  counter += 1;
  return counter;
}

const id1 = Symbol('id');
const id2 = Symbol('id');
const obj1 = { a: 1 };
const obj2 = { a: 1 };

const memoizedFoo = memoize(foo);
console.log(memoizedFoo(id1)); // 2
console.log(memoizedFoo(id1)); // 2
console.log(memoizedFoo(id2)); // 3
console.log(memoizedFoo(id2)); // 3
console.log(memoizedFoo(obj1)); // 4
console.log(memoizedFoo(obj1)); // 4
console.log(memoizedFoo(obj2)); // 5
console.log(memoizedFoo(obj2)); // 5
console.log(memoizedFoo(5)); // 6
console.log(memoizedFoo(5)); // 6
console.log(memoizedFoo(4)); // 7
console.log(memoizedFoo(4)); // 7