设计模式的观察的模式究竟是怎么样的呢?它的叫法有多种,不过我们需要知道的是它的原理而非它的名字是怎么样称呼的。
这里,我们把它们看成是:订阅者--发布者的关系。
在说这个模式之前,我们或许更应该知道这个模式可以怎么来用?作用是什么?
其实,它的原理并不难,我们举的例子是报社与订报人的关系。我们想想,如果报社有最新的报纸出了,报社就会给每个订报人发布一条有报纸出了的消息,让每个订报人都能够看到。
这么看来,我们就看可以知道,报社其实充当的就是一个管理订报人的角色。然后有情况的时候,统一发布一条消息让订阅者知道。这样就起到了类似一键更新的功能。
好,说了这么多,我们看看具体的实现的步骤吧。
首先,你需要给你的发布者和订阅者抽象出一系列方法,然后再通过继承来实现这些方法。最后,就可以实例化出来进行一一匹配了。
或许你会想到,为什么不直接实现出方法呢?其实,我也不是很清楚,不过,我可以肯定的是,因为抽象的方法,可以让你的思路更加清晰。
好了,下面就直接来看看我用C++实现的观察者模式的代码吧:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
//订阅者抽象方法
class PeopleInterface {
public:
//实现自我更新
virtual void update(string msg) = 0;
};
//订阅者抽象方法的具体实现
class People
:public PeopleInterface
{
public:
//实例化时给订阅者定义一个名字
People(string name)
{
m_name = name;
}
//实现自我更新:通过收到发布者的消息来实现自我的更新
virtual void update(string msg)
{
cout <<m_name<< "收到了消息:" << msg<<endl;
}
private:
string m_name;
};
//发布者抽象方法
class OfficeInterface
{
public:
virtual void addObserver(People *p) = 0;
virtual void deleteObserver(People *p) = 0;
virtual void sendMsg(string s) = 0;
};
//发布者抽象方法的具体实现
class Brightoffice
:public OfficeInterface
{
public:
//添加订阅者
virtual void addObserver(People *p)
{
this->oldPeople_vec.push_back(p);
}
//删除订阅者
virtual void deleteObserver(People *p)
{
vector<People*>::iterator iter = oldPeople_vec.begin();
for (iter; iter != oldPeople_vec.end(); iter++)
{
if (*iter == p){
oldPeople_vec.erase(iter);
return;
}
}
}
//给订阅者发布更新消息
virtual void sendMsg(string msg)
{
People *temp;
for (int i = 0; i < oldPeople_vec.size(); i++)
{
temp = oldPeople_vec.at(i);
temp->update(msg);
}
}
private:
vector<People*>oldPeople_vec;
};
int main()
{
//实例出一个发布者
auto office = new Brightoffice();
//实例出多个订阅者
auto p1 = new People("张三");
auto p2 = new People("李四");
auto p3 = new People("王五");
//将订阅者添加到已经实例化出来的发布者中
office->addObserver(p1);
office->addObserver(p2);
office->addObserver(p3);
//发布者消息更新,这时每个订阅者都会收到来自发布者的更新消息
office->sendMsg("新的报纸出了!");
//突然李四不想再定这家报社的报纸了,退出报社。此时将不再接收到这家报社的更新消息
cout << "李四退出了报社!" << endl;
office->deleteObserver(p2);
office->sendMsg("新的报纸又出了");
getchar();
return 0;
}
这里我用了STL库中的vector来进行订阅者的存储,其实可以使用其他的容器。
其实作为一个发布者,这里我仅仅实现了简单的添加与删除,其实还可以更完整一点,就是可以添加查找某个订阅者等等。
结果如下:
观察者模式其实也是挺有用的,比如在游戏中,服务器要给客户端的玩家发送系统公告等消息。好了,希望这篇文章对读者有帮助~