转载请注明t1234xy4原创:http://blog.csdn.net/t1234xy4/article/details/52432559#
观察者模式简介
又称发布——订阅模式,主要用于类对象之间消息通知。当主要对象发生信息变更后,与之相关联的信息也应该变更显示。
主要的操作:
1、先创建主体subject;
2、创建观察者,同时告诉它要关注的主体subuject。
3、主体subject要知道哪些人关注了它,因此需要维护一个list。同时将观察者放入list中。操作位Attach()。如果不关注了需要Detach()。
4、观察者要主动拉取信息,pull()。
这个类图比较简单,但实现比较麻烦。实现需要注意:
1、同一个观察者不要attach两次或两次以上。(除非你希望给同一个观察者发送多次重复的信息,但没多少意义)
2、如果一个实例提前消亡了,在消亡前应该Detach掉,否者下次发送消息将导致不可预知的风险。(当然每次发送消息的时候,可以对每一个实例是否存在检查)
3、其他的还没有遇到。
类图
代码
subject代码部分
#pragma once
#include "Observer.h"
#include <string>
#include <iostream>
#include <list>
using namespace std;
class ConcreteSubject{
public:
ConcreteSubject();
virtual void Attach(Observer* ob);
virtual void Dettch(Observer* ob);
virtual void NotifyAll();
virtual void changeState(std::string _state);
virtual std::string getState();
~ConcreteSubject();
protected:
std::string state;
std::list<Observer *> _obList;
};
#include "ConcreteSubject.h"
ConcreteSubject::ConcreteSubject():state("one"){
}
void ConcreteSubject::Attach(Observer* ob){
std::cout<<"Insert Observer:"<<ob->getObserverId()<<std::endl;
std::list<Observer *>::iterator it;
for(it=_obList.begin();it!=_obList.end();it++)
if((*it)==ob){
std::cout<<" has been in the List"<<std::endl;
return;
}
_obList.push_back(ob);
}
void ConcreteSubject::Dettch(Observer* ob){
std::cout<<"Observer "<<ob->getObserverId()<<" : ";
_obList.remove(ob);
std::cout<<"removed";
}
void ConcreteSubject::NotifyAll(){
std::list<Observer *>::iterator it;
for(it = _obList.begin();it!=_obList.end();it++)
{
(*it)->pull();
}
}
void ConcreteSubject::changeState(std::string _state){
state = _state;
}
std::string ConcreteSubject::getState(){
return state;
}
ConcreteSubject::~ConcreteSubject(){
std::cout<<"ConcreteSubject "<<std::endl;
}
观察者部分
#pragma once
#include "ConcreteSubject.h"
#include <string>
#include <iostream>
class ConcreteObserver:
public Observer{
protected:
ConcreteObserver(void);
public:
ConcreteObserver(ConcreteSubject* _sub,int id);
virtual void pull();
virtual int getObserverId();
~ConcreteObserver();
private:
ConcreteSubject* subject;
int Id;
};
#include "ConcreteObserver.h"
ConcreteObserver::ConcreteObserver(){
}
ConcreteObserver::ConcreteObserver(ConcreteSubject* _sub,int id):subject(_sub),Id(id){
}
void ConcreteObserver::pull(){
std::cout <<"Observer "<<Id<<": "<< subject->getState() <<std::endl;
}
int ConcreteObserver::getObserverId(){
return Id;
}
ConcreteObserver::~ConcreteObserver(){
std::cout<<" ~ConcreteObserver :"<<Id<<std::endl;
}