1. 将数据和“数据的视图”进行分离,保持两者之间的低耦合。
2. “数据类”保持独立性,“视图类”依赖“数据类”
3. “数据类”中维护所有视图实例的引用(顶级父类引用),“视图类”中维护所依赖的数据实例的引用。
4. 数据发生更新时数据实例根据“视图类”所提供的接口,执行更新操作。
#include <iostream>
#include <vector>
using namespace std;
class Subject
{
vector <class Observer* > views; /* observer 父类指针 */
int value; /* 数据 */
public:
void attach(Observer *obs)
{
views.push_back(obs);
}
void setVal(int val) /* 更新数据,同时通知观察者读取数据 */
{
value = val;
notify();
}
int getVal()
{
return value;
}
void notify();
};
class Observer
{
Subject *model; /* 指针指向观察者所依赖的“数据”实例 */
int denom;
public:
Observer(Subject *mod, int div)
{
model = mod;
denom = div;
model->attach(this); /* 将自己加入到“数据”所维护的观察者集合中 */
}
virtual void update() = 0; /* 数据读取方式由具体子类进行实现 */
protected: /* 以下方法客户没法进行访问 */
Subject* getSubject()
{
return model;
}
int getDivisor()
{
return denom;
}
};
void Subject::notify()
{
for (int i = 0; i < views.size(); i++)
views[i]->update(); /* 不同的观察者有不同的数据读取方式,此处为多态,update()是父类方法 */
}
/* 不同观察者的具体实现 */
class DivObserver: public Observer
{
public:
DivObserver(Subject *mod, int div): Observer(mod, div){}
void update()
{
int v = getSubject()->getVal(), d = getDivisor();
cout << v << " div " << d << " is " << v / d << '\n';
}
};
class ModObserver: public Observer
{
public:
ModObserver(Subject *mod, int div): Observer(mod, div){}
void update()
{
int v = getSubject()->getVal(), d = getDivisor();
cout << v << " mod " << d << " is " << v % d << '\n';
}
};
int main()
{
Subject subj;
DivObserver divObs1(&subj, 4);
DivObserver divObs2(&subj, 3);
ModObserver modObs3(&subj, 3);
subj.setVal(14);
}