• 设计模式之观察者模式(Observer)


    观察者模式通常的叫法叫做订阅-发布模式,类似于报刊杂志的订阅,观察者和被观察者就是读者和邮局的关系,读者先要在邮局订阅想要的报刊,当报刊发行时,邮局会将报刊邮寄到读者家里。观察者(Observer)和被观察者(Listener)也是这种关系,Observer将自己attach到Listener中,当Listener触发时Notify所有Observer.

    作用

    在观察者模式中,被观察者维护观察者对象的集合,当被观察者对象变化时,它会通知观察者。观察者模式主要是用于解决对象之间一对多的关系。

    类视图

    实现

    class Observer 
    {
    public:
        virtual ~Observer() {};
        virtual void Update(const std::string &msg)= 0; 
    protected:
        Observer(){};
    };
    
    
    class Listener
    {
    public:
        virtual ~Listener() {};
        void attach(Observer* obsvr) 
    	{
    		m_observers.push_back(obsvr);
    	}
        void remove(Observer* obsvr)
    	{
    		m_observers.remove(obsvr);
    	}
        void notify(const std::string &msg)
    	{
    		list<Observer*>::iterator iter = m_observers.begin();  
            for(; iter != m_observers.end(); iter++)  
                (*iter)->Update(msg); 
    	}
    private:  
        list<Observer* > m_observers; //观察者链表 
    };
    
    
    class logRunner : public Listener
    {
    public:
    	virtual ~logRunner(){};
    	void addmsg(const std::string &msg)
    	{
    		nofity(msg);
    	}
    }
    
    class logGui : public Observer
    {
    public:
    	virtual ~Observer(){};
    	void Update(const std::string &msg)
    	{
    		cout<< "Gui log show : "<< msg <<endl;
    	}
    }
    
    class logFile : public Observer
    {
    public:
    	virtual ~Observer(){};
    	void Update(const std::string &msg)
    	{
    		cout<< "file log write : "<< msg <<endl;
    	}
    }
    
    class logDebug : public Observer
    {
    public:
    	virtual ~Observer(){};
    	void Update(const std::string &msg)
    	{
    		cout<< "Debug log out : "<< msg <<endl;
    	}
    }
    
    
    class logDataBase : public Observer
    {
    public:
    	virtual ~Observer(){};
    	void Update(const std::string &msg)
    	{
    		cout<< "DataBase log in : "<< msg <<endl;
    	}
    }
    
    int main()
    {
    	logRunner Runner;
    	logGui gGui;
    	logFile gFile;
    	logDebug gDebug;
    	logDataBase gDataBase;
    	
    	Runner.attach(&gGui);
    	Runner.attach(&gFile);
    	Runner.attach(&gDebug);
    	Runner.attach(&gDataBase);
    	
    	Runner.addmsg("app is setup");
    }
    
    

    Observer中update一般为纯虚,通过子类各自实现,这里只是保证调用的接口一致,Listener中的attach、remove、notify一般建议不进行虚化,子类不用关心其内部的聚合内容,通过调用notify实现消息分发即可。当然也可以虚化,将这一系列的操作放到子类进行实现。
    调用者应该注意在多线程环境中的使用环境,做好数据的同步工作。

    应用场景

    1. 当一个对象改变需要通知到其他对象,而我们不确定由多少对象需要通知时;
    2. 当一个对象必须通知其他对象,而不需要知道对象是什么实现时;
    3. 对于一堆对象,包含同样的状态或同样的数据,通过同一个条件进行更新时。
  • 相关阅读:
    for ,foreach ,map 循环的区别
    PHP生成验证码图片
    Google自动打印
    MYSQL定时任务
    PHP 多维数组将下标从0开始
    MYSQL常用函数
    PHP 手机短信发送验证码
    php 限制标题长度,将一个中文转换成一个字符
    MYSQL 模糊查询
    MYSQL AND 和 OR
  • 原文地址:https://www.cnblogs.com/chencarl/p/8727768.html
Copyright © 2020-2023  润新知