设计模式-行为-Observer(观察者)模式
典型的应用就是MVC模式
定义了一对多的关系,一个对象的改变,所依赖的其他对象都将获得通知并且更新。
场景1:看电视,喜欢看这个频道的 会选择看这个频道,
场景2:类似于订阅自己关心的状态,该状态的消息来了,那么就会得到通知
观察者模式缺点也很明显
1.每次都要广播筛选 合适的观察者

例1
头文件
#include "PublicHeaders.h"
#include <vector>
#include <string>
class Observer;
class Subject
{
public:
virtual void Attach(Observer*) = 0;
virtual void Detach(Observer*) = 0;
virtual void Notify() = 0;
void setState(const std::string&state)
{
this->_state = state;
}
const std::string& getState()const
{
return _state;
}
private:
std::string _state;
protected:
std::vector<Observer*> _observers;
};
class ConCreateSubject :public Subject
{
public:
virtual void Attach(Observer*) override;
virtual void Detach(Observer*)override;
virtual void Notify() override;
};
class Observer
{
public:
virtual void Update(const std::string &state) = 0;
};
class ConCreateObserverA :public Observer
{
public:
virtual void Update(const std::string& state)override
{
if (state == "A")
{
cout << __FUNCTION__ << endl;
}
}
};
class ConCreateObserverB :public Observer
{
public:
virtual void Update(const std::string& state)override
{
if (state == "B")
{
cout << __FUNCTION__ << endl;
}
}
};
void testObserver();
源文件
#include "Observer.h"
void ConCreateSubject::Attach(Observer*observer)
{
_observers.push_back(observer);
}
void ConCreateSubject::Detach(Observer*observer)
{
auto iter = std::find(_observers.begin(), _observers.end(), observer);
if (iter != _observers.end())
{
_observers.erase(iter);
}
}
void ConCreateSubject::Notify()
{
for (int i = 0; i < _observers.size(); ++i)
{
_observers[i]->Update(this->getState());
}
}
void testObserver()
{
ConCreateSubject *sub = new ConCreateSubject;
auto a1 = new ConCreateObserverA;
sub->Attach(a1);
auto a2 = new ConCreateObserverA;
sub->Attach(a2);
auto b1 = new ConCreateObserverB;
sub->Attach(b1);
sub->setState("A");
sub->Notify();
sub->Detach(a1);
sub->Notify();
}
例2
游戏中实现的观察者实例
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public delegate void HandlerNotifyCenter(System.Object arg);
[System.Serializable]
class Recver
{
public string name;
public GameObject recver;
public HandlerNotifyCenter handler;
public Recver()
{
}
public void InVoke(System.Object arg)
{
handler(arg);
}
}
public class NotifyCenter : MonoBehaviour
{
static public NotifyCenter ins;
List<Recver> recvers = new List<Recver>();
void Awake()
{
ins = this;
}
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void addRecver(GameObject recver, string name, HandlerNotifyCenter handler)
{
// gameObject.SendMessage(msg);
Recver x = new Recver();
x.name = name;
x.handler = handler;
x.recver = recver;
recvers.Add(x);
}
public void removeRecver(GameObject recver, string name)
{
foreach (Recver obj in recvers)
{
if (name == obj.name && recver == obj.recver)
{
recvers.Remove(obj);
}
}
}
public void sendMessage(string msg, System.Object arg)
{
foreach (Recver obj in recvers)
{
if (msg == obj.name)
{
obj.InVoke(arg);
}
}
}
}
添加观察者
NotifyCenter x = NotifyCenter.ins;
x.addRecver(gameObject, "addCoin", new HandlerNotifyCenter(addCoin));
public void addCoin(System.Object obj)
{
}
例3
class NotifyCenter
{
public:
static NotifyCenter *ins;
static NotifyCenter*getInstance()
{
if (ins == nullptr)
{
ins = new NotifyCenter;
}
return ins;
}
void SendMessage(string name, void* data)
{
auto &func = _listeners[name];
if (func )
{
func(data);
}
}
void addListener(string name, std::function<void(void*data)> callback)
{
_listeners[name] = callback;
}
private:
std::unordered_map< string, std::function<void(void*data)> > _listeners;
};
NotifyCenter*NotifyCenter::ins = nullptr;
int main()
{
//添加接受者
NotifyCenter::getInstance()->addListener("john", [=](void *data)
{//回调
cout << (char*)data<<" call me " << endl;
});
//添加接受者
NotifyCenter::getInstance()->addListener("jack", [=](void *data)
{
//回调
cout << (char*)data << " call me " << endl;
});
//发送消息
NotifyCenter::getInstance()->SendMessage("john","hk");
//发送消息
NotifyCenter::getInstance()->SendMessage("john", "");
//发送消息
NotifyCenter::getInstance()->SendMessage("11", "");
system("pause");
return 0;
}
当然用vector 就能实现一对多了