观察者模式(Observer):定义了对象间的一种一对多的关系,当一个对象改变时,所有依赖他的对象都得到通知并自动更新。
动机:
将一个系统划分成一系列相互协作的类有一个常用的副作用:需要维护相关对象间的一致性,我们不希望为了维护一致而是的各类紧密耦合,因为主要降低了系统的可复用性,因此利用观察者模式可以描述建立一种各层次之间的关系的模型,当被依赖的某个对象的状态发生变更时,所有依赖的对象的状态都得到更新。当前很多大型代码结构中都用到了一种事件机制,这种事件机制其实就是观察者模式的一种,订阅者订阅目标的某个时期,当目标触发该事件时通知订阅者。如Windows开发中我们订阅系统的鼠标单击事件,当我们鼠标单击我们程序的窗口时,操作系统就会发布鼠标单击系统给相应的订阅者,订阅者执行相应的操作。
适用性:
1、当一个抽象模型有两个方面,其中一个方面依赖另外一个方面。将这二者封装在独立的对象中以使它们可以独立的改变和复用。
2、当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
3、当一个对象必须通知其他对象,而它又不能假定其他对象时谁。换言之,你不希望对象之间是紧密耦合的。
通用观察者模式UML类图
Subject(目标):抽象的目标类,提供了一个抽象的Notify,和增加/删除对象引用的的接口。
ConcreteSubject:具体目标类,实现了抽象目标类的接口,同时增加了设置对象状态属性和获取状态属性的方法。
注意的是:目标类维护了一个观察者的对象列表,需要订阅Subject对象状态改变的类都必须向具体的目标对象注册自己,当具体目标类对象状态改变时,根据维护的观察者对象列表来通知观察者对象改变。
Obserber(观察者/订阅者):观察者抽象类,提供了一个更新状态的抽象接口。
ConcterteObserver1/ConcreteObserver2:具体观察者类,实现抽象类的接口,并增加了一个显示当前状态的函数。
实例代码如下:
Observer.h
#ifndef Observer_h_
#define Observer_h_
#include <iostream>
#include <list>
class Observer;
const int NET_STAT_UNCONNET = 0;
const int NET_STAT_LISTENING = 1;
const int NET_STAT_CONNCTED = 2;
class Subject
{
public:
virtual ~Subject(){};
virtual bool Attach(Observer*)=0;
virtual bool Detach(Observer*)=0;
virtual void Notify() = 0;
void SetState(int state){ this->m_state = state; }
int GetState(){ return m_state; }
protected:
int m_state;
};
class ConcreteSubject :public Subject
{
public:
ConcreteSubject();
virtual ~ConcreteSubject(){};
void Notify();
virtual bool Attach(Observer*);
virtual bool Detach(Observer*);
private:
std::list<Observer*> m_observer_List;
};
class Observer
{
public:
virtual ~Observer(){};
virtual void Update(Subject*)=0;
void ShowState(){ std::cout << "state: " << m_state << std::endl; }
protected:
int m_state;
};
class ConcrtrObserver1:public Observer
{
public:
virtual void Update(Subject*);
ConcrtrObserver1();
virtual ~ConcrtrObserver1(){};
};
class ConcrtrObserver2 :public Observer
{
public:
virtual void Update(Subject*);
ConcrtrObserver2();
virtual ~ConcrtrObserver2(){};
};
#endif
Observer.cpp
#include "Observer.h"
#include <algorithm>
ConcreteSubject::ConcreteSubject()
{
m_state = NET_STAT_UNCONNET;
}
bool ConcreteSubject::Attach(Observer* pObser)
{
m_observer_List.push_back(pObser);
std::cout << "Insert an Observer\n";
return true;
}
bool ConcreteSubject::Detach(Observer* pObser)
{
std::list<Observer*>::iterator it;
for (it = m_observer_List.begin(); it != m_observer_List.end(); it++)
{
if (*it == pObser)
{
m_observer_List.erase(it);
std::cout << "Erase an observer\n";
break;
}
}
return true;
}
void ConcreteSubject::Notify()
{
std::list<Observer*>::iterator it;
for (it = m_observer_List.begin(); it != m_observer_List.end(); it++)
{
(*it)->Update(this);
}
}
ConcrtrObserver1::ConcrtrObserver1()
{
m_state = NET_STAT_UNCONNET;
}
void ConcrtrObserver1::Update(Subject* pSubject)
{
this->m_state = pSubject->GetState();
ShowState();
}
ConcrtrObserver2::ConcrtrObserver2()
{
m_state = NET_STAT_UNCONNET;
}
void ConcrtrObserver2::Update(Subject* pSubject)
{
this->m_state = pSubject->GetState();
ShowState();
}
客户端代码:
#include"Observer.h"
int main()
{
ConcrtrObserver1 *pObser1 = new ConcrtrObserver1();
ConcrtrObserver2 *pObser2 = new ConcrtrObserver2();
ConcrtrObserver1 *pObser3 = new ConcrtrObserver1();
ConcrtrObserver2 *pObser4 = new ConcrtrObserver2();
ConcreteSubject *pSubject = new ConcreteSubject();
pSubject->Attach(pObser1);
pSubject->Attach(pObser2);
pSubject->Attach(pObser3);
pSubject->Attach(pObser4);
pSubject->SetState(NET_STAT_LISTENING);
pSubject->Notify();
pSubject->Detach(pObser3);
pSubject->SetState(NET_STAT_CONNCTED);
pSubject->Notify();
delete pObser1;
delete pObser2;
delete pObser3;
delete pObser4;
delete pSubject;
return 0;
}
实例代码运行结果:
观察者模式的最重要目标是接触耦合,让耦合的双发都依赖于抽象,而不应该依赖于具体,从而使得各自的变化不会影响到另一边的变化。(依赖倒换原则)