C ++中用于对象变更识别的设计模式?

时间:2018-09-20 17:48:52

标签: c++ design-patterns

我正在寻找一种机制/设计模式,该模式允许以某种方式设置对象,以便机制会通知对象在特定存在点(例如构造)之后是否发生了更改。理想情况下,该对象也可以获取有关其更改的信息。

我正在想象一种智能指针和/或接口,它记录了写访问并将其传达给对象。

可能的用例: 对象的内容已从文件中加载,如果销毁后对其进行了更改,则应将其写入文件。

通常,您可以实现对象的所有设置方法来分别计算写访问次数。

class A
{
    string filename;
    unsigned int altered;
    int m_a, m_b, M_c;
public:
    A(string filename) : filename(filename), altered(0) { /* parse file */ }
    ~A() { if(altered) {/* write out to file */} } 

    void setA(int a) {altered++; m_a = a}
    void setB(int b) {altered++; m_b = b}
    void setC(int c) {altered++; m_c = c}
};

我觉得很难维护而且不太优雅。同样,这种解决方案对于其他类型的对象不是很容易移植。

2 个答案:

答案 0 :(得分:1)

我不认为有一个简单的通用解决方案,因为您需要做出许多决策。例如,在您的代码中,即使altered也会增加a==m_a。在某些情况下,这可能是正确的选择,但在其他情况下却并非如此。无论如何,这里有一些简单的方法,可以让您选择在修改成员的情况下要做的事情:

#include <iostream>
using namespace std;

template <typename T> 
struct modification_tracking {
    using clean_up_t = void(*)(const T&);
    modification_tracking(const T& t,clean_up_t clean_up) : 
        t(t), clean_up(clean_up) {}
    ~modification_tracking(){ if(modified) clean_up(t); }
    void set(const T& v){
        modified = t != v;
        t = v;
    }
private:
    T t;
    clean_up_t clean_up;
    bool modified = false;
};

struct foo {
    modification_tracking<int> member{ 1, [](const int& x){ std::cout << x << '\n';}};
};    

int main() {        
    foo f1;
    foo f2;
    f1.member.set(3);
}

也许带有自定义删除器的智能指针可以以更好的方式执行相同的操作,甚至更多。如果对象是轻量级的,您甚至可以考虑存储原始对象,并在超出范围时进行比较。还是计算一个哈希值..确实有太多选择;)

答案 1 :(得分:0)

我想不出任何可以神奇地识别出文件已更改的模式。除非您认为从文件中进行散列然后比较散列是可以接受的。在某些时候,您将必须更改类的状态,以便它写入更改后的文件。这可以通过多种方式完成。

您可以实现的一件事是modify函数,该函数可以更改类的状态并为用户提供更改类的可变版本的选项。

void modify(const std::function<void(Mutable_A&)>& modifier) // Implemented in A
{
    modifier(/* the internal stucture */);
    this->writeFile = []{/* write out to file */}; // Then called in destructor
}

然后像这样从外部调用

a.modify([](auto& a){
    a.m_a = 2;
    a.m_b = 3;
    a.setA(2); // If set is prefered
});

这避免了必须添加任意的altered计数器。您还可以检查modifier回调函数是否实际更改,并且如果更改了某些内容,则仅分配writeFile。在这种情况下,set函数只能在Mutable_A中实现。至于如何称呼这种模式,我不知道。