观察者模式
观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
观察者模式是一种对象行为型模式。UML类图如下:
图中有两个基类:
- Observer(观察者类)
- ConcretObserver
- Subject (目标类)
- ConcretSubject
Observer负责观察Subject状态的变化,Subject负责在自己状态改变的时候通知观察者类。下面放代码:
- observer.h
#ifndef OBSERVER_H
#define OBSERVER_H
#include <QString>
#include "subject.h"
class Observer
{
public:
Observer(QString name);
virtual ~Observer();
virtual void Update(Subject* obj);
protected:
QString m_Name;
};
class ConcretObserver : public Observer
{
public:
ConcretObserver(QString name);
virtual ~ConcretObserver();
};
#endif // OBSERVER_H
- observer.cpp
#include "observer.h"
#include <QDebug>
Observer::Observer(QString name)
{
m_Name = name;
}
Observer::~Observer()
{
}
void Observer::Update(Subject* obj)
{
QString action;
if(m_Name == "李白")
action = "使用灵动的一技能快速避开";
else if(m_Name == "香香")
action = "使用翻滚,并走位找机会打出翻滚之后的加成伤害";
qDebug() << m_Name << " " << action;
}
ConcretObserver::ConcretObserver(QString name)
:Observer (name)
{
}
ConcretObserver::~ConcretObserver()
{
}
- subject.h
#ifndef SUBJECT_H
#define SUBJECT_H
#include <QVector>
class Observer;
class Subject
{
public:
Subject(QString name);
virtual ~Subject();
virtual void Attach(Observer* obs);
virtual void Detach(Observer* obs);
virtual void Notify();
virtual void SetAction(QString act);
virtual QString GetAction();
private:
QString m_Name;
QString m_Action;
QVector<Observer*> m_ObserverVec;
};
class ConcretSubject : public Subject
{
public:
ConcretSubject(QString name);
virtual ~ConcretSubject();
};
#endif // SUBJECT_H
- subject.cpp
#include "subject.h"
#include "observer.h"
Subject::Subject(QString name)
{
m_Name = name;
}
Subject::~Subject()
{
}
void Subject::Attach(Observer *obs)
{
m_ObserverVec.push_back(obs);
}
void Subject::Detach(Observer *obs)
{
QVector<Observer*>::iterator it;
for(it = m_ObserverVec.begin(); it != m_ObserverVec.end(); ++it)
{
if(*it == obs)
{
m_ObserverVec.erase(it);
}
}
}
void Subject::Notify()
{
for(Observer* obs : m_ObserverVec)
{
obs->Update(this);
}
}
void Subject::SetAction(QString act)
{
m_Action = act;
}
QString Subject::GetAction()
{
return m_Action;
}
ConcretSubject::ConcretSubject(QString name)
: Subject (name)
{
}
ConcretSubject::~ConcretSubject()
{
}
- main.cpp
#include <QCoreApplication>
#include "observer.h"
#include "subject.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Subject* sub = new ConcretSubject("敌方牛魔");
Observer* obj1 = new ConcretObserver("李白");
Observer* obj2 = new ConcretObserver("香香");
sub->Attach(obj1);
sub->Attach(obj2);
sub->SetAction("使用了大闪");
sub->Notify();
return a.exec();
}
牛魔使用了大闪,李白和想想分别用了自己的位移技能进行了躲避
作为一个喜欢在王者峡谷驰骋的男人在此模式中把峡谷世界和观察者模式的设计动机机智的联系起来方便读者理解。其实游戏开发中的很多场景都是类似观察者模式的,峡谷的每个人都会根据其他角色的状态变化做出相应的动作,同时自己的动作也会通知到出自己之外的其他9个峡谷英雄,所以这些峡谷英雄其实是生活正在观察者模式之中的男人和女人~
观察者模式遵照了以下几个设计原则:
- 依赖倒转原则
- 开放封闭原则
参考《大话设计模式》和 https://design-patterns.readthedocs.io/zh_CN/latest/index.html