前言
观察者模式是使用频率最高最常用的模式之一,观察者模式要解决的问题为:建立一个一( Subject)对多( Observer) 的依赖关系, 并且做到当“一” 变化的时候, 依赖这个“一”的多也能够同步改变。
模式的定义和特点
观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
如上定义,在观察者模式之中,发生改变的对象是观察目标,接收到改变通知的所有对象都称为观察者,一个目标可以对应多个观察者。
观察者模式的实现
举一个简单的例子。我记得QQ上有一个功能叫做上线离线通知吧,例如你喜欢一个女生,所以你很想和她聊天,只要她一上线,你就要找她聊天,但是你又不可能时刻关注着她的上线离线情况。这个时候qq的离线上线通知就起作用了。你可以把她添加到上线通知的队列里,然后只要她一上线,qq就会给你发通知,然后你就可以愉快的和她聊天了。哈哈哈,这么说就很好理解观察者模式为什么又叫发布订阅模式了,在这个例子中就好比你向qq订阅了某项服务,然后qq会在服务更新时发布到你的qq里。当然有可能不止你一个人喜欢那个女生,可能同学乙也喜欢那个女生,也将其添加到上线通知队列中,然后也可以在女生上线时得到通知,这就是一对多的关系。
在上面的例子中,女生就是具体的观察目标,你和同学乙就是具体的观察者。但是一般在观察者模式中,具体的观察目标和具体的观察者不会有调用的关系,否则就会把具体的观察目标和具体的观察者耦合起来,这违反了面向对象的设计原则。
观察者模式的主要角色如下:
1.抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
2.具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
3.抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
4.具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
下面就来看一下如何实现我们上面讲的qq上线通知的例子。
首先是抽象观察者角色,提供了一个接收通知的接口。
class Observer
{
public:
virtual void update(bool Isonline) = 0;
};
上面就是抽象的观察者角色,具体的观察者则继承抽象的观察者。
接下来是抽象的主题,也叫抽象的观察目标。
class Subject
{
public:
virtual void registerobserver(Observer *ob) = 0;
virtual void removeobserver(Observer *ob) = 0;
virtual void notifyobserver() = 0;
};
可见,抽象的观察目标仅仅是提供了是三个接口,即注册观察者,注销观察者和通知观察者,具体的观察目标就继承抽象的观察目标。
接下来是具体的观察目标:
class Gril:public Subject
{
private:
vector<Observer*> observers; //定义观察者队列,这里用vector来实现
vector<Observer*>::iterator it;
bool Isonline;
public:
void registerobserver(Observer *ob)
{
observers.push_back(ob);//将具体的观察者入列
}
void removeobserver(Observer *ob)
{
observers.pop_back();//观察者出列
}
void notifyobserver()
{
for(it = observers.begin();it!=observers.end();it++)
(*it)->update(Isonline);//发布通知给所有队列里的观察者
}
void set(bool is)
{
Isonline = is;
notifyobserver();
}
};
再看一下具体的观察者如何实现:
class Observser1:public Observer
{
private:
bool Isonline;
Subject *obj;
public:
Observser1(Subject *obj)
{
this->obj = obj;
this->obj->registerobserver(this);//在构造函数中调用注册函数,使自己成为gril的观察者
}
void update(bool Isonline)
{
this->Isonline = Isonline;
display();
}
void display()
{
if(Isonline)
{
cout << "Observser1::gril online" << endl;
}
else
{
cout << "Observser1::gril offline" << endl;
}
}
};
class Observser2:public Observer
{
private:
bool Isonline;
Subject *obj;
public:
Observser2(Subject *obj)
{
this->obj = obj;
this->obj->registerobserver(this);//在构造函数中调用注册函数,使自己成为gril的观察者
}
void update(bool Isonline)
{
this->Isonline = Isonline;
display();
}
void display()
{
if(Isonline)
{
cout << "Observser2::gril online" << endl;
}
else
{
cout << "Observser2::gril offline" << endl;
}
}
};
在上面的具体观察者代码中,我们创建了两个观察者的类。
完整的程序:
#include <iostream>
#include <vector>
using namespace std;
class Observer
{
public:
virtual void update(bool Isonline) = 0;
};
class Subject
{
public:
virtual void registerobserver(Observer *ob) = 0;
virtual void removeobserver(Observer *ob) = 0;
virtual void notifyobserver() = 0;
};
class gril:public Subject
{
private:
vector<Observer*> observers;
vector<Observer*>::iterator it;
bool Isonline;
public:
void registerobserver(Observer *ob)
{
observers.push_back(ob);
}
void removeobserver(Observer *ob)
{
observers.pop_back();
}
void notifyobserver()
{
for(it = observers.begin();it!=observers.end();it++)
(*it)->update(Isonline);
}
void set(bool is)
{
Isonline = is;
notifyobserver();
}
};
class Observser1:public Observer
{
private:
bool Isonline;
Subject *obj;
public:
Observser1(Subject *obj)
{
this->obj = obj;
this->obj->registerobserver(this);
}
void update(bool Isonline)
{
this->Isonline = Isonline;
display();
}
void display()
{
if(Isonline)
{
cout << "Observser1::gril online" << endl;
}
else
{
cout << "Observser1::gril offline" << endl;
}
}
};
class Observser2:public Observer
{
private:
bool Isonline;
Subject *obj;
public:
Observser2(Subject *obj)
{
this->obj = obj;
this->obj->registerobserver(this);
}
void update(bool Isonline)
{
this->Isonline = Isonline;
display();
}
void display()
{
if(Isonline)
{
cout << "Observser2::gril online" << endl;
}
else
{
cout << "Observser2::gril offline" << endl;
}
}
};
int main()
{
gril* obj = new gril();
Observser1* A1 = new Observser1(obj);
Observser2* A2 = new Observser2(obj);
obj->set(true);//上线通知
obj->set(false);//离线通知
return 1;
}
运行结果如下:
可见,两个观察者都收到了gril的上线和离线通知。