我想重构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
答案 0 :(得分:2)
一种选择是在NestedCache
类上具有3个方法:
如果需要,您可以使用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