1,设计模式是经过多年的经验总结出来的一套使用特定场景的模型框架,就好比盖房子,用固定不错的模型框架进行房子主体的构建过程。之后再根据具体的情况添加具体的处理即可。
观察者模式:
根据名称顾名思义,该模式应该具有观察者和给观察者两种类型的对象,如下图uml图所示:
如上图所示,为观察者模式的uml模型图,从图中可看到对应的模型结构,该模式的主要特点就是,每一个观察者都观察被观察者对象,当被观察者对应有状态发生变变化时,通知通知所有的观察者,这样观察这就能观察到对应的目标的变化状态。并且该模型时一种一对多的关系模型。
如下代码所示:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// 观察者
class Observer {
public:
virtual void update(string msg) = 0;
};
// 被观察者
class Subject {
public:
virtual int addObserver(Observer *obs) = 0;
virtual int attachObserver(Observer *obs) = 0;
virtual int notifyObserver(string msg) = 0;
};
class SonSubject:public Subject {
public:
virtual int addObserver(Observer *obs)
{
vecObsList.push_back(obs);
}
virtual int attachObserver(Observer *obs)
{
for(int i = 0;i < vecObsList.size();++i)
{
if(vecObsList[i] == obs)
{
vecObsList[i] = NULL;
break;
}
}
}
virtual int notifyObserver(string msg)
{
for(int i = 0;i < vecObsList.size();++i)
{
if(vecObsList[i] != NULL)
{
vecObsList[i]->update(msg);
}
}
}
private:
vector<Observer*> vecObsList;
};
class SonObserver:public Observer{
public:
SonObserver(string name)
{
this->name = name;
}
void update(string msg)
{
cout<<"update msg = "<<name.c_str()<<" = "<<msg.c_str()<<endl;
}
private:
string name;
};
int main()
{
Subject* sj = new SonSubject();
SonObserver ob1("111");
SonObserver ob2("222");
SonObserver ob3("333");
sj->addObserver(&ob1);
sj->addObserver(&ob2);
sj->addObserver(&ob3);
sj->notifyObserver("hello"); //变更,观察者都同步接受变更
return 0;
}
特点:
降低了耦合性,并使两者都依赖于了抽象层,彼此两边各自变化都不会影响另外一边。
使用场景:
A,关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
B,事件多级触发场景。
C.跨系统的消息交换场景,如消息队列、事件总线的处理机制。
缺点:
观察者多的时候,通知的时候是按照顺序来通知的,这样比较费时间,可根据考虑进行异步的消息通知模式。另外可根据具体的情况,使用众多观察者模式定期的扫描观察者的过程,类似一个订阅过程,当观察者出现状态更改的时候,根据被观察者只需要将对应的消息状态进行更改,而观察者通过扫描对应的消息状态就能知道对应被观察者的状态信息,但是这样可能涉及到多线程共享资源的情况,可根据队列信息,让每个观察者独享一个队列中的一个块,这样多个观察者同事访问的时候,只需要访问属于自己的块即可,避免了资源竞争引起的枷锁阻塞。(可能这种模式还有缺点,可根据实际情况,进行不同类型的优化处理。后续如果好的模型例子,在进行补充更新)