背景
在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”,一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过去亲密,将使软件不能很好的抵御变化。
特点
观察者模式定义对象间的一对多(变化)的依赖关系,以便当一个对象的状态发生改变时,所有依赖它的对象都得到通知并且自动更新。
使用面向对象的抽象,观察者模式使得我们可以独立地改变目标与观察者,从而使得二者之间的依赖关系达到松耦合。
目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
观察者自己决定是否需要订阅通知,目标对象对此一无所知。
观察者模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的额一个重要组成部分。
C++代码实现
//Subject.h
#pragma once
#include<list>
#include<string>
using namespace std;
class Observer;
class Subject {
public:
virtual ~Subject();
virtual void detach(Observer* obs);
virtual void attach(Observer* obs);
virtual void notify();
virtual void setState(const string& str) = 0;
virtual string getState() = 0;
protected:
Subject();
private:
list<Observer*>* obs;
};
class ConcreteSubject :public Subject {
public:
~ConcreteSubject();
ConcreteSubject();
void setState(const string& str);
string getState();
private:
string state;
};
//Subject.cpp
#include"Observer.h"
#include"Subject.h"
#include<iostream>
#include<list>
using namespace std;
Subject::Subject() {
obs = new list<Observer*>;
}
Subject::~Subject() {
}
void Subject::attach(Observer* obs) {
this->obs->push_front(obs);
}
void Subject::detach(Observer* obs) {
this->obs->remove(obs);
}
void Subject::notify() {
list<Observer*> ::iterator it = obs->begin();
for (; it != obs->end(); it++) {
(*it)->update(this);
}
}
ConcreteSubject::ConcreteSubject() {
state = '\0';
}
ConcreteSubject::~ConcreteSubject() {
}
void ConcreteSubject::setState(const string& str) {
state = str;
}
string ConcreteSubject::getState() {
return state;
}
//Observer.h
#pragma once
class Subject;
#include<string>
using namespace std;
class Observer {
public:
virtual ~Observer();
virtual void update(Subject* sub) = 0;
virtual void printinfo() = 0;
protected:
string state;
Observer();
};
class ConcreteObserverA :public Observer {
public:
~ConcreteObserverA();
ConcreteObserverA(Subject* sub);
virtual Subject* getSubject();
void update(Subject* sub);
void printinfo();
private:
Subject* sub;
};
class ConcreteObserverB :public Observer {
public:
~ConcreteObserverB();
ConcreteObserverB(Subject* sub);
virtual Subject* getSubject();
void update(Subject* sub);
void printinfo();
private:
Subject* sub;
};
//Observer.cpp
#include"Observer.h"
#include"Subject.h"
#include<list>
#include<string>
#include<iostream>
using namespace std;
Observer::Observer() {
state = '\0';
}
Observer::~Observer() {
}
ConcreteObserverA::ConcreteObserverA(Subject* sub) {
this->sub = sub;
this->sub->attach(this);
}
ConcreteObserverA::~ConcreteObserverA() {
this->sub->detach(this);
if (sub) {
delete sub;
}
}
Subject* ConcreteObserverA::getSubject() {
return sub;
}
void ConcreteObserverA::printinfo() {
cout << "ConcreteObserverA:" << sub->getState() << endl;
}
void ConcreteObserverA::update(Subject* sub) {
state = sub->getState();
printinfo();
}
ConcreteObserverB::ConcreteObserverB(Subject* sub) {
this->sub = sub;
this->sub->attach(this);
}
ConcreteObserverB::~ConcreteObserverB() {
this->sub->detach(this);
if (sub) {
delete sub;
}
}
void ConcreteObserverB::printinfo() {
cout << "ConcreteObserverB:" << sub->getState() << endl;
}
void ConcreteObserverB::update(Subject* sub) {
state = sub->getState();
printinfo();
}
Subject* ConcreteObserverB::getSubject() {
return sub;
}
//Main.cpp
#include"Observer.h"
#include"Subject.h"
#include<iostream>
using namespace std;
int main() {
Subject* sub = new ConcreteSubject();
Observer* obsa = new ConcreteObserverA(sub);
Observer* obsb = new ConcreteObserverB(sub);
sub->setState("old");
sub->notify();
sub->setState("new");
sub->notify();
return 0;
}
代码说明
在观察模式当中,Subject维护一个list容器作为存储所有观察者的容器。每次调用notify()都会遍历容器中Observer对象,并且调用Observer的update操作用来通知改变状态。目标状态state可以由于Subject改变也可以由于Observer里面调用Subject的SetState操作改变。
运行程序会发现当Subject处于old的时候,两个观察者都是old,当Subject处于new的时候,两个观察者都是new。
运行结果