观察者模式

观察者模式适用于在一个一对多模型中,一者状态变化,多者需要根据变化做出相应调整的情况,下面我们通过一个简单的例子简单说明观察者模式的设计方法
注:本利旨在说明观察者模式的设计思想,例子中存在一定的内存泄露没有处理

假设我们有一台电脑主机,这台电脑主机不干别的事,只是向屏幕发送一个数字。
同时有多台显示器连接到这台主机上,并根据发送来的数字做自己的逻辑处理再显示出来
首先我们做一个只有一个显示器的情况

class Display
{
public:
	void update(int num)
	{
		m_num = num;
		show();
	}

	void show()
	{
		std::cout << m_num << std::endl;
	}
private:
	int m_num;
};

class Computer
{
public:
	void setNum(int num)
	{
		m_num = num;
		numChange();
	}
	int getNum()
	{
		return m_num;
	}
	
	void numChange()
	{
		m_display->update(m_num);
	}

	void setDisplay(Display *display)
	{
		m_display = display;
	}

private:
	int m_num;
	Display *m_display;
};

int main(int argc, char **argv)
{
	Display *display = new Display;

	Computer *computer = new Computer;
	computer->setDisplay(display);

	computer->setNum(10);

	computer->setNum(100);

	return 0;
}

在上面代码中,我们首先定义了一个显示器和一个主机,并为主机绑定了显示器。当主机的数字变化时,会自动调用显示器的更新方法,将新的数字显示出来。

现在,我们将情景变的复杂一些,如果我们需要有两台显示器,一台显示器用来显示主机发送的原始数据,另一台需要将主机发送的数据加1后再显示出来。
可见,在上面的代码中,想实现这个功能非常麻烦,不但要添加一个显示器类的定义,还要修改主机类的定义,而且每次需要添加或删除显示器,都要修改主机类。而观察者模式就是解决类似情况的,我们只需要添加一个显示器类就可以了,而不需要修改主机类,下面是代码

class Observer
{
public:
	virtual void update(int num)
	{
		m_num = num;
		show();
	}
	virtual void show() = 0;

protected:
	int m_num;
};

class Subject
{
public:
	virtual void registerObserver(Observer *observer) = 0;
	virtual void removeObserver(Observer *observer) = 0;
	virtual void notifyObserver() = 0;
};

class Display1 : public Observer
{
public:
	void show() override
	{
		std::cout << m_num << std::endl;
	}
};

class Display2 : public Observer
{
public:
	void show() override
	{
		std::cout << m_num + 1 << std::endl;
	}
};

class Computer : public Subject
{
public:
	void setNum(int num)
	{
		m_num = num;
		numChange();
	}
	int getNum()
	{
		return m_num;
	}
	
	void numChange()
	{
		notifyObserver();
	}

	void registerObserver(Observer *observer) override {
		m_observerList.push_back(observer);
	}

	void removeObserver(Observer *observer) override {
		for (std::vector<Observer*>::iterator iter = m_observerList.begin(); iter != m_observerList.end();)
		{
			if (*iter == observer)
				iter = m_observerList.erase(iter);
			else
				iter++;
		}
	}

	void notifyObserver() override {
		for (int i = 0; i < m_observerList.size(); i++) {
			m_observerList.at(i)->update(m_num);
		}
	}

private:
	int m_num;
	std::vector<Observer*> m_observerList;
};

int main(int argc, char **argv)
{
	Display1 *display1 = new Display1();
	Display2 *display2 = new Display2();

	Computer *computer = new Computer();


	computer->registerObserver(display1);
	computer->registerObserver(display2);
	computer->setNum(10);
	std::cout << "========================================\n";
	computer->removeObserver(display1);
	computer->setNum(100);

	return 0;
}

这里,我们添加了两个虚基类
Subject:就是“被观察”的角色,它将所有观察者对象的引用保存在一个集合中。
Observer:是抽象的“观察”角色,它定义了一个更新接口,使得在被观察者状态发生改变时通知自己。
在本例中,我们创建了一个被观察者主机,和两个观察者显示器1和2,对象创建完成后,将显示器1和2添加到被观察者主机的观察者集合中
每当被观察者的数据变化时,就向观察者集合中的所有观察者发送数据变化事件,观察者接收到被观察者发送的变化事件并接收到变化后的数据后,根据自己的逻辑进行显示,本例中1是原样显示,2是加1后显示
被观察者还可以将某个观察者从自己的观察者集合中删除,这样数据变化时就不会向已删除的观察者发送变化事件了。