假设有一个类Data,它不仅包含可以修改的数据,还包含构建在包含的数据成员上的重要成员函数。
进一步假设有一个HandleData类,它获取一个指向Data实例的指针。 HandleData获取数据并计算一些重要的成员编号(已在初始化时)。初始化和数据更改期间的数字计算很重要,因为一次又一次地使用函数成员调用计算它们是昂贵的(例如执行集成)。 如果数据发生变化,HandleData将通过更新数字来适应变化。
到目前为止,问题只是观察者模式。现在,HandleData还提供另一个名为TreatHandleData的类,这样Data的更改意味着HandleData中的更改,这再次暗示了TreatHandleData的更改。在所有情况下,为了减少计算时间,每次Data / HandleData更改时都必须初始化一些数字。
如果所有这些类都需要可复制,那么混乱似乎是完整的。
我真的希望看到我在下面写的内容的一些替代方案。特别是因为在我的情况下,所有类必须从一个类派生。它似乎不对。
我的简单尝试是:
#include <algorithm> // remove
#include <memory> // shared_ptr
#include <assert.h>
#include <iostream> // cout, cerr, endl
#include <vector>
class MutualObserver
{
public:
MutualObserver() {}
// copy ctor resets the list of observers
MutualObserver(const MutualObserver & src) : observer(0) {}
virtual ~MutualObserver() {};
// assign op. must be empty to not have a list of observers that persists
MutualObserver& operator = ( const MutualObserver &rhs ) { return *this; }
// adds observer
void add ( MutualObserver * o )
{
bool good = true;
for ( uint i = 0; i<observer.size(); i++)
if ( observer[i] == o ) good = false;
if ( good && (o != NULL) ) observer.push_back(o);
}
// removes observer
void remove ( MutualObserver * o )
{
if ( o == NULL )
std::cout<<" in Data::remove - observer is NULL "<<std::endl;
bool good = true;
for ( uint i = 0; i<observer.size(); i++)
if ( observer[i] == o ) good = false;
if (good && o!=NULL )
observer.erase
( std::remove( observer.begin(), observer.end(), o),observer.end() );
}
/// updates obserer o
void update_observer ( MutualObserver * o )
{
for ( uint i = 0; i<observer.size(); i++ )
if ( observer[i] == o ) observer[i]->update_yourself();
}
/// updates all observers
void update_all_observers ()
{
for (uint i = 0; i<observer.size(); i++)
{
observer[i]->update_yourself();
}
}
/// updates all important members esp. of derived classes
/// observer method, should be implemented for all observers
virtual void update_yourself () {}
protected:
std::vector<MutualObserver*> observer;
};
class Data : public MutualObserver
{
public:
Data () : A(42.) {}
void setA ( double x ) { A = x; update_all_observers(); }
double getA () { return A; }
double multiply ( double x ) { return A * x; }
private:
double A;
};
class HandleData : public MutualObserver
{
double important_variable;
std::shared_ptr<Data> mySource;
public:
HandleData ( std::shared_ptr<Data> source )
: mySource(source), important_variable(0.)
{
assert( source != NULL );
mySource->add(this);
update_yourself();
}
HandleData ( const HandleData &src )
: MutualObserver(src), mySource( src.mySource ),
important_variable( src.important_variable )
{
assert( mySource != NULL );
mySource->add(this);
update_yourself();
}
virtual ~HandleData() { if ( mySource!=NULL ) mySource->remove(this); }
virtual void update_yourself ()
{
double A = mySource->getA();
important_variable = A *2.*3.14;
}
double getVariable() const { return important_variable; }
};
class TreatHandleData : public MutualObserver
{
double important_variable;
std::shared_ptr<HandleData> mySource;
public:
TreatHandleData ( std::shared_ptr<HandleData> source )
: mySource(source), important_variable(0.)
{
assert( source != NULL );
mySource->add(this);
update_yourself();
}
TreatHandleData ( const TreatHandleData &src )
: MutualObserver(src), mySource( src.mySource ),
important_variable( src.important_variable )
{
assert( mySource != NULL );
mySource->add(this);
update_yourself();
}
virtual ~TreatHandleData() { if ( mySource!=NULL ) mySource->remove(this); }
virtual void update_yourself ()
{
double A = mySource->getVariable();
important_variable = A * 365.;
}
double getVariable() const { return important_variable; }
};
int main()
{
std::shared_ptr<Data> observable ( new Data() );
std::shared_ptr<HandleData> observer ( new HandleData(observable) );
std::shared_ptr<TreatHandleData> myTHD ( new TreatHandleData(observer) );
// copy
std::shared_ptr<Data> observable2 ( new Data( *observable ) );
std::shared_ptr<HandleData> observer2 ( new HandleData(*observer) );
std::shared_ptr<TreatHandleData> myTHD2 ( new TreatHandleData(*myTHD) );
std::cout << "initial Data: "<< observable->getA() << std::endl;
std::cout << "initial HandleData: "<< observer->getVariable() << std::endl;
std::cout << "initial TreatHandleData: "<< myTHD->getVariable() << std::endl;
std::cout << " COPY: " << std::endl;
std::cout << "initial Data: "<< observable2->getA() << std::endl;
std::cout << "initial HandleData: "<< observer2->getVariable() << std::endl;
std::cout << "initial TreatHandleData: "<< myTHD2->getVariable() << std::endl;
double a = 99.31232;
std::cout << " Changing A to " << a << std::endl;
observable->setA( a );
std::cout << " (diff) changed Data: "<< observable->getA() << std::endl;
std::cout << " (diff) changed HandleData: "<< observer->getVariable() << std::endl;
std::cout << " (diff) changed TreatHandleData: "<< myTHD->getVariable() << std::endl;
std::cout << " COPY: " << std::endl;
std::cout << " (same) changed Data: "<< observable2->getA() << std::endl;
std::cout << " (diff) changed HandleData: "<< observer2->getVariable() << std::endl;
std::cout << " (same) changed TreatHandleData: "<< myTHD2->getVariable() << std::endl;
return 0;
}
结果是:
初始数据:42
初始HandleData:263.76
初始TreatHandleData:96272.4
COPY:
初始数据:42
初始HandleData:263.76
初始TreatHandleData:96272.4
将A更改为99.3123
(差异)改变数据:99.3123
(差异)改变了HandleData:623.681
(差异)更改了TreatHandleData:96272.4
COPY:
(同)更改数据:42
(差异)改变了HandleData:623.681
(同)更改了TreatHandleData:96272.4
应该如此。
答案 0 :(得分:0)
根据我的理解,你不想在每次getter调用时重新计算HandleData和TreeHandleData上的数据,因为计算是扩展的。
为什么不使用延迟更新方法是getter检查底层数据是否已更改并仅在这种情况下重新计算。这样就根本不需要使用观察者模式。