c++设计模式之观察者模式

本文深入讲解了观察者模式的定义、特点及实现方式,通过QQ上线通知的例子详细阐述了一对多依赖关系的处理机制,包括抽象主题、具体主题、抽象观察者和具体观察者等关键角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

观察者模式是使用频率最高最常用的模式之一,观察者模式要解决的问题为:建立一个一( 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的上线和离线通知。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值