缓存的getter / calculate模式|具有依赖关系跟踪的boost类

时间:2013-07-18 11:32:34

标签: c++ design-patterns boost proxy c++03

“缓存计算”/“缓存的getter”是否有通用模式或即用型升级类?

我的意思是这样的:

class Test{
public:
     Value getValue() const;
protected:
     Value calculateValue() const;//REALLY expensive operation.
     mutable bool valueIsDirty;
     mutable Value cachedValue;
}

Value Test::getValue() const{
     if (valueIsDirty){
         cachedValue = calculateValue();
         valueIsDirty = false;
     }
     return cachedValue;
}

我可以使用std::pair<Value, bool>并将getValue/calculateValue转换为宏,但如果值取决于其他值(存储在其他类中)和这些值,这实际上没有用也可以缓存。

这种“模式”是否有现成的解决方案?目前我手动处理这样的缓存值,但这不是“漂亮”。

限制:
c ++ 03标准。允许提升。

2 个答案:

答案 0 :(得分:1)

Proxy design pattern可以帮助解决这个问题。

典型的实现将定义一个类ValuePtr,其行为就像普通的Value*一样,即它有一个重载的operator->operator*。但是这些运算符不是直接访问底层Value对象,而是包含决定加载或重新计算实际值的逻辑。这种额外的间接级别将封装代理逻辑。

如果您需要将refences计算到其他对象,可能std::shared_ptr<Value>可用作ValuePtr中的underyling数据类型。

有关代码示例,请参阅this siteBoost.Flyweight也可能会有所帮助。

答案 1 :(得分:1)

这是我最终使用的:

template<typename T, typename Owner> class CachedMemberValue{
public:
    typedef T (Owner::*Callback)() const;
    T get(){
        if (dirty){
            cachedValue = (owner->*calculateCallback)();
            dirty = false;
        }
        return cachedValue;
    }
    const T& getRef(){
        if (dirty){
            cachedValue = (owner->*calculateCallback)();
            dirty = false;
        }
        return cachedValue;
    }
    void markDirty(){
        dirty = true;
    }
    CachedMemberValue(Owner* owner_, Callback calculateCallback_)
        :owner(owner_), calculateCallback(calculateCallback_), dirty(true){
    }
protected:
    Owner *owner;
    Callback calculateCallback;
    bool dirty;
    T cachedValue;
private:
    CachedMemberValue(const CachedMemberValue<T, Owner>&){
    }
    CachedMemberValue<T, Owner>& operator=(const CachedMemberValue<T, Owner>&){
        return *this;
    }
};

用法:

class MyClass{
    public:
        int getMin() const{
            return cachedMin.get();
                }
            void modifyValue() { /*... calculation/modification*/ cachedMin.markDirty();}
        MyClass(): cachedMin(this, &MyClass::noncachedGetMin){}
    private:
        int noncachedGetMin() const{ /*expensive operation here*/ ... }
        mutable CachedMemberValue<int, MyClass> cachedMin;
};