我想重构Cache
类,这样它就不会违反单一责任原则(SRP(。
但是,我很难弄清楚如何将类中不必要的步骤重构Cache
memoize
函数中。理想情况下,我将在Cache
类中有两种方法get
和set
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
一种选择是在NestedCache
类上使用 3 个方法:
- getNestedMap,在给定键数组的情况下遍历映射
- getMap,获取特定 Map 中键的值
- setKeyIfNeed,用于在 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