观察者模式(Observer Pattern ) 当对象之间存在一对多的关系时,则使用观察者模式。 观察者模式属于行为型模式。
意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知一样并被自动更新。
解决问题
一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
如何解决
使用面向对象技术,可以将这种依赖关系弱化。
优点
1. 观察者和被观察者是抽象耦合的;
2. 建立了一套触发机制
缺点
1. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间;
2. 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃
3. 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景
1. 有多个子类共有的方法,且逻辑相同;
2. 重要的、复杂的方法,可以考虑作为模板方法
注意事项
1. JAVA 中已经有了对观察者模式的支持类;
2. 注意循环引用;
3. 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式
UML类图
Subject(目标)
---目标知道它的观察者。可以有任意多个观察者观察同一个目标
---提供注册和删除观察者对象的接口
---一般用一个抽象类或者一个接口实现
Observer(观察者)
---为所有的具体观察者定义一个接口,在得到主题的通知时更新自己
---一般用一个抽象类或者一个接口实现
ConcreteSubject(具体目标)
---将有关状态存入具体现察者对象
---在具体主题的内部状态改变时,给所有登记过的观察者发出通知
---一般用一个具体子类实现
ConcreteObserver(具体观察者)
---维护一个指向ConcreteSubject对象的引用
---具体现察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与目标的状态相协调
---通常用一个具体子类实现
C++实现
最近中国股市起起伏伏,当然了起伏就用商机,小明发现商机后果断想入市,买入了中国证券,他想在电脑客户端上,网页上,手机上,iPad上都可以查看到该证券的实时行情,这种情况下我们应该怎么设计我们的软件呢?我们可以这样:小明的所有客户端上都订阅中国证券这个股票,只要股票一有变化,所有的客户端都会被通知到并且被自动更新。
code:
//观察者模式
class _Secretary;
class StockObserver//看股票的同事类(观察对象---观察者)
{
public:
StockObserver(string _strName, _Secretary* _strSub)
:name(_strName)
, Sub(_strSub)
{}
void Update();
private:
string name;
_Secretary* Sub;
};
class _Secretary //秘书类(主题对象--通知者)
{
vector<StockObserver> ob;
public :
string action;
void Add(StockObserver _ob)
{
ob.push_back(_ob);
}
void Remove(size_t index)
{
if (index >= 0 && index < ob.size())
ob.erase(ob.begin() + index);
}
void Notify()
{
vector<StockObserver>::iterator it = ob.begin();
for (; it != ob.end(); ++it)
{
it->Update();
}
}
};
void StockObserver:: Update()
{
cout << name << " : " << Sub->action << ", begin to work" << endl;
}
客户端:
int test_Observe() //观察者模式
{
//创建通知者
_Secretary* p = new _Secretary();
//观察者
StockObserver* s1 = new StockObserver("Jack", p );
StockObserver* s2 = new StockObserver("Rose", p);
//加入通知队列
p->Add(*s1);
p->Add(*s2);
//事件
p->action = "The boss is coming...";
//通知
p->Notify();
//动态删除
p->Remove(0);
p->Notify();
delete p;
delete s1;
delete s2;
p = NULL;
s1 = s2 = NULL;
system("pause");
return 0;
}
总结
观察者模式在23个设计模式中的地位是非常高的,我们基本上各大框架中都是随处可见。这里总结的不够全面,日后在学习和工作中如果碰到需要补充的,我会继续补充,同时也希望各位读者给出您的意见。