观察者
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新.
实例
main.cc:
#include <windows.h>
#include "runner_people.h"
#include "volunteer_people.h"
#include "sponsor_subject.h"
/*
design_pattern:"observer"
Marathon, the organizers need to send some information to the participants
according to the weather conditions, if it rains, athletes and volunteers will
wear a disposable raincoat, if it does not rain, we will as usual
*/
int main(){
SponsorSubject *sponsor = new SponsorSubject();
RunnerPeople *zhang_san = new RunnerPeople(sponsor,"zhang san");
RunnerPeople *li_si = new RunnerPeople(sponsor,"li si");
VolunteerPeople *volunteer = new VolunteerPeople(sponsor,"wang wu");
sponsor->Add(zhang_san);
sponsor->Add(li_si);
sponsor->Add(volunteer);
sponsor->Notify("rainy day,putting on a raincoat!");
/*
sponsor->Notify("sunny day,as usual!");
*/
//clear
delete sponsor;
delete zhang_san;
delete li_si;
delete volunteer;
system("Pause");
return 0;
}
Subject:
//subject.h
#ifndef HELENDP_SOURCE_SUBJECT_H_
#define HELENDP_SOURCE_SUBJECT_H_
#include "people.h"
#include <list>
class Subject{
public:
Subject();
~Subject();
virtual void Add(People *people) = 0;
virtual void Remove(People *people) = 0;
virtual void Notify(string message) = 0;
protected:
list<People *> people_list_;
};
#endif
//subject.cc
#include "subject.h"
Subject::Subject(){
}
Subject::~Subject(){
}
SponsorSubject:
//sponsor_subject.h
#ifndef HELENDP_SOURCE_SPONSOR_SUBJECT_H_
#define HELENDP_SOURCE_SPONSOR_SUBJECT_H_
#include "people.h"
#include <string>
#include <list>
#include "subject.h"
using namespace std;
class SponsorSubject : public Subject{
public:
SponsorSubject();
~SponsorSubject();
void Add(People *people);
void Remove(People *people);
void Notify(string message);
string notify_message_;
};
#endif
//sponsor_subject.cc
#include "sponsor_subject.h"
SponsorSubject::SponsorSubject(){
}
SponsorSubject::~SponsorSubject(){
}
void SponsorSubject::Add(People * people){
people_list_.push_back(people);
}
void SponsorSubject::Remove(People * people){
people_list_.remove(people);
}
void SponsorSubject::Notify(string message){
notify_message_ = message;
for(list<People *>::iterator iterator = people_list_.begin();
iterator != people_list_.end();++iterator){
(*iterator)->Update();
}
}
People:
//people.h
#ifndef HELENDP_SOURCE_PEOPLE_H_
#define HELENDP_SOURCE_PEOPLE_H_
#include <string>
using namespace std;
class People{
public:
People(string name);
~People();
virtual void Update() = 0;
void SetName(string name);
string GetName();
private:
string name_;
};
#endif
//people.cc
#include "people.h"
People::People(string name){
name_ = name;
}
People::~People(){
}
void People::SetName(string name){
name_ = name;
}
string People::GetName(){
return name_;
}
RunnerPeople:
//runner_people.h
#ifndef HELENDP_SOURCE_RUNNER_PEOPLE_H_
#define HELENDP_SOURCE_RUNNER_PEOPLE_H_
#include "people.h"
#include "sponsor_subject.h"
class RunnerPeople : public People{
public:
RunnerPeople(SponsorSubject *sponsor_subject,string name);
~RunnerPeople();
void Update();
private:
SponsorSubject *sponsor_subject_;
};
#endif
//runner_people.cc
#include "runner_people.h"
#include <iostream>
using namespace std;
RunnerPeople::RunnerPeople(SponsorSubject *sponsor_subject,string name)
:People(name){
sponsor_subject_ = sponsor_subject;
}
RunnerPeople::~RunnerPeople(){
}
void RunnerPeople::Update(){
cout << "runner(" << this->GetName() << ") get message:" << sponsor_subject_->notify_message_<< endl;
}
VolunteerPeople:
//volunteer_people.h
#ifndef HELENDP_SOURCE_VOLUNTEER_PEOPLE_H_
#define HELENDP_SOURCE_VOLUNTEER_PEOPLE_H_
#include "people.h"
#include "sponsor_subject.h"
class VolunteerPeople : public People{
public:
VolunteerPeople(SponsorSubject *sponsor_subject,string name);
~VolunteerPeople();
void Update();
private:
SponsorSubject *sponsor_subject_;
};
#endif
//volunteer_people.cc
#include "volunteer_people.h"
#include <iostream>
using namespace std;
VolunteerPeople::VolunteerPeople(SponsorSubject *sponsor_subject,string name)
:People(name){
sponsor_subject_ = sponsor_subject;
}
VolunteerPeople::~VolunteerPeople(){
}
void VolunteerPeople::Update(){
cout << "volunteer(" << this->GetName() << ") get message:" << sponsor_subject_->notify_message_ << endl;
}
代码和UML图(EA)工程文件,最后会整理打包上传.
UML类图
结构
- Subject(Subject):目标类,观察者所关注的目标.
- ConcreteSubject(SponsorSubject):具体目标类.
- Observer(People):观察者抽象类.
- ConcreteObserver(RunnerPeople,VolunteerPeople):具体观察者类.
优点
- 观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色.
- 观察者模式在观察目标和观察者之间建立一个抽象的耦合.
- 观察者模式支持广播通信.
- 观察者模式符合“开闭原则”的要求.
缺点
- 如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间.
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃.
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化.