C++登录后通知各个显示页面,采用观察者模式

327 阅读3分钟

「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

我们在做有用户登录的开发项目的手,总会遇到这样的需求,用户登录后会通知各个显示页面,更改显示状态,或者是取消登录之后也会通知各个页面更改显示状态。

假设,程序中所有页面都需要显示用户的登录状态,那么无论是在哪个页面上进行登录后,都需要更新其它页面的显示状态。最最方便的用法无外乎就是使用观察者模式了。

观察者模式定义:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新

在这里用这种设计模式简直是太合适了。

那么,接下来我就详细的介绍在开发中该如何应用吧!

第一步:定义监听者接口

我们更改了数据之后该如何通知呢?

或者说是用什么消息触发呢?

在这里,我们就需要定义一个接收的接口,哪个页面需要监听数据的变化,哪个页面就必须实现当前接口

class CUserBasicDataListenner
{
public:
    //是否退出登录?false 登录  true退出登录
    virtual void UpdateUserBasicData(bool bExitLogin) = 0;
};

第二步:监听类定义

定义了监听接口之后,那么我们需要记录有哪些页面要有操作变化的功能。

这里,需要记录那些可以显示登录状态改变的窗口类指针

class CNotifierModeMsg
{
public: //对外开放接口
	virtual void registerListenner(CUserBasicDataListenner *ptr) = 0;
	virtual void removeListenner(CUserBasicDataListenner* ptr) = 0;
	virtual void notifyEvent(bool bExitLogin) = 0;
};

registerListenner:记录 需要监听的 操作类指针

removeListenner:移出 不需要监听的 操作类指针

notifyEvent:状态更改时,进行的消息处理

第三步:使用监听类

我们可以定义一个叫做UserManager的类,用来操作监听事件。

记录所有操作的监听指针,以及消息的分发操作。

对于这种纯虚类的使用,一般情况下我们会采用继承的方式。

那么,我们该如何存储那些监听类呢?

这里可以采用容器的方式,我才用的是set容器,使用这种容器的好处是防止重复性存储。

在存储监听指针的时候,我们最好的方式需要判断该指针是否被存储过?

std::set<CUserBasicDataListenner*>::iterator itfind = m_setListenners.find(ptr);
if (itfind == m_setListenners.end())
{
	m_setListenners.insert(ptr);
}

移出指针操作:

void SingletonUserManager::removeListenner(CUserBasicDataListenner *ptr)
{
	std::set<CUserBasicDataListenner*>::iterator itlist = m_setListenners.begin();
	for (itlist; itlist != m_setListenners.end(); )
	{
		if (*itlist == ptr)
		{
			itlist = m_setListenners.erase(itlist);
		}
		else
			itlist++;
	}
}

更改操作状态,这里就用到了notifyEvent方法了。

当我们更改了参数状态时,将对set容器中存储的所有监听指针进行更新

void SingletonUserManager::notifyEvent(bool bExitLogin)
{
	std::set<CUserBasicDataListenner*>::iterator itList = m_setListenners.begin();
	for (itList; itList != m_setListenners.end(); itList++)
	{
		if (*itList != nullptr)
		{
			(*itList)->UpdateUserBasicData(bExitLogin);
		}
	}
}

第四步:页面窗口对监听事件的使用

当我们应用到实际的窗口中时,也需要继承定义的监听类:CUserBasicDataListenner

当窗口创建后,我们需要将该窗口的指针进行记录,只有在释放窗口时,才需要移出当前窗口的指针,保证了指针的唯一性。

并且,在每个特定的实现页面中,需要重写UpdateUserBasicData,以保证触发状态更新后可以实时接收新数据。

以这种方式,我们就可以实现,一个页面数据变化,所有需要更换数据的页面同时变换了。

今天的更新到这里就结束了~

如有问题,我们可以相互学习,共同进步!

共勉!!