[设计模式]_[观察者模式在窗口之间消息传递的使用例子]

场景:多窗口之间的通讯,使用观察者模式来给观察者发送通知消息,让观察者及时响应信息,减少窗口之间包含其他窗口的引用,减少耦合。下面看一个模型图


上图:两个模式对话框和主窗口之间的关系,模式对话框只和主窗口之间进行绑定,两个模式对话框之间没有直接的关系,它们之间要进行通讯,可以通过主窗口来进行消息的转发 ,避免多个窗口之间相互引用,造成意外的情况发生。


#include <stdio.h>
#include <stdlib.h> 
#include <list>    
#include <string>  
#include <iostream>  
  
using namespace std;  
  
enum NotifyType   
{  
    kUpdateOutputDir = 0,  
    kUpdateTitle  
  
};  
  
*/  
  /** 
 * 1.抽象父类,不能实例化,观察者. 
 */  

class ObserverBase  
{  
public: 
	ObserverBase()  
    {  
    }  
  
    virtual ~ObserverBase()  
    {  
    }  
    virtual void Attach(ObserverBase* observer);  
    virtual void Detach(ObserverBase* observer);  
    virtual void Notify(void *userdata,int type);  
    
  
    virtual void Update(void* userdata,int type)  
    {  
    }  
  
private:  
    list<ObserverBase*> observer_list_;  
};  
  
//Subject  
  
void ObserverBase::Attach(ObserverBase* observer)  
{  
    observer_list_.push_back(observer);  //把观察者加入到队列中,添加绑定
}  
  
void ObserverBase::Detach(ObserverBase* observer)  
{  
    observer_list_.remove(observer);  //把观察者从队列移除,解除绑定
}  
  
void ObserverBase::Notify(void *userdata,int type)  
{  
	
    list<ObserverBase*>::iterator it;  
    for (it = observer_list_.begin(); it != observer_list_.end();  
            it++)  
    {  
        (*it)->Update(userdata,type);  
    }  
}  
  
  
class MqjFirstDialog : public ObserverBase  
{  
public:  
    MqjFirstDialog(){}  
    ~MqjFirstDialog(){}  
  
    void Update(void* userdata,int type)  
    {  
        //处理指定的消息  
        switch(type)  
        {  
            case kUpdateOutputDir:  
              {  
                output_dir_ =  *((string*)userdata);  
                std::cout << "I am in MqjFirstDialog: " << output_dir_ << std::endl;  
                break;  
             }   
        }  
    } 
public:
    std::string title_;  
    std::string output_dir_;  
};  
  
class MqjSecondDialog : public ObserverBase  
{  
public:  
    MqjSecondDialog(){}  
    ~MqjSecondDialog(){}  
  
    void Update(void* userdata,int type)  
    {  
        //1.增加判断类型就是只想处理指定的消息  
        switch(type)  
        {  
            case kUpdateOutputDir:  
              {  
                output_dir_ =  *((string*)userdata);  
                std::cout << "I am in MqjSecondDialog: " << output_dir_ << std::endl;  
                break;  
             }   
        }  
    } 
public:
    std::string title_;  
    std::string output_dir_;  
};  
  
  
class MqjMainWindow :public ObserverBase  
{  
    public:  
    MqjMainWindow(){}  
    ~MqjMainWindow(){}  
  
    void Update(void* userdata,int type)  
    {  
        //处理指定的消息  
        switch(type)  
        {  
            case kUpdateTitle:  
            {  
                string title =  *((string*)userdata);  
                //修改输出目录  
                std::cout << "I am MqjMainWindow: " << title << std::endl;  
                break;  
            }   
        }  
    }  
  
};   
  
  
int main(int argc, char* argv[])  
{  
    MqjFirstDialog first_dialog;  
	MqjSecondDialog second_dialog;
    MqjMainWindow main_window_;  
  
    //1.互相监听,注意,这里是动态添加监听,并不是互相之间直接引用各自的对象.  
	first_dialog.Attach(&main_window_);  
    main_window_.Attach(&first_dialog);
  
    first_dialog.title_ = "I am first";  
    first_dialog.Notify(&first_dialog.title_,kUpdateTitle);//通知MainWindow  
  
    string output = "D:\\first-dialog\\common";  
    main_window_.Notify(&output,kUpdateOutputDir);//通知firstDialog 
	
	first_dialog.Detach(&main_window_);//解除 first_dialog 和main_window之间的绑定
	main_window_.Detach(&first_dialog);
	
	second_dialog.Attach(&main_window_);  
    main_window_.Attach(&second_dialog);

	second_dialog.title_ = "I am second";  
    second_dialog.Notify(&second_dialog.title_,kUpdateTitle);//通知MainWindow  
  
    output = "D:\\second-dialog\\common";  
    main_window_.Notify(&output,kUpdateOutputDir);//通知secondDialog  

	return 0;
}  
运行结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值