设计模式-行为-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 就能实现一对多了

Scroll Up