[设计模式]_[中级]_[观察者模式在项目中实际使用例子]

来源:互联网 发布:linux如何查看cpu 编辑:程序博客网 时间:2024/05/22 16:44


场景:

1. 比如在界面开发中,多个窗口之间需要通讯,比较常见的方法就是各个窗口之间包含对其他窗口的引用,之后在需要时通过其他窗口的引用来调用相应的函数获取相应的值;

但是这个确定还是比较明显的,就是会造成窗口之间的依赖和耦合,想想测试或编译某个窗口时另一个窗口必须是没问题的,而另一个窗口编译又依赖它,这样成了反复依赖

导致编译不过或修改其中一个另一个就得相应的改。很麻烦,不好维护。

2. 还有的不切实际的解决办法是在窗口之间发送事件,比如qt得信号或win32的消息,但是这样会造成消息的泛滥,资源的滥用,而且都是主线程来处理事件,何必发事件呢?


解决办法:

1. 使用观察者模式来给观察者发送通知,让观察者及时响应,减少耦合。看实际的例子吧:


main.cpp

/* * File:   main.cpp */#include <list>#include <stdio.h>#include <time.h>#include <string>#include <iostream>using namespace std;enum NotifyType {    kUpdateOutputDir = 0,    kUpdateTitle};class Observer;/** * 1.抽象父类,不能实例化,目标. */class Subject{public:    virtual ~Subject()    {    }    virtual void Attach(Observer* observer);    virtual void Detach(Observer* observer);    virtual void Notify(void *userdata,int type);protected:    Subject()    {    }private:    list<Observer*> observers_;};/** * 1.抽象父类,不能实例化,观察者. */class Observer{public:    virtual ~Observer()    {    }    virtual void Update(void* userdata,int type)    {    }protected:    Observer()    {    }private:};//Subjectvoid Subject::Attach(Observer* observer){    observers_.push_back(observer);}void Subject::Detach(Observer* observer){    observers_.remove(observer);}void Subject::Notify(void *userdata,int type){    list<Observer*>::iterator theIterator;    for (theIterator = observers_.begin(); theIterator != observers_.end();            theIterator++)    {        (*theIterator)->Update(userdata,type);    }}class DhDialog : public Subject, public Observer{public:    DhDialog(){}    ~DhDialog(){}    void Update(void* userdata,int type)    {        //1.增加判断类型就是只想处理指定的消息        switch(type)        {            case kUpdateOutputDir:              {                output_dir_ =  *((string*)userdata);                std::cout << "I am in DhDialog: " << output_dir_ << std::endl;                break;             }         }    }    std::string title_;    std::string output_dir_;};class DhOutputWindow : public Subject, public Observer{    public:    DhOutputWindow(){}    ~DhOutputWindow(){}    void Update(void* userdata,int type)    {        //1.增加判断类型就是只想处理指定的消息        switch(type)        {            case kUpdateTitle:            {                string title =  *((string*)userdata);                //修改输出目录                std::cout << "I am DhOutputWindow: " << title << std::endl;                break;            }         }    }}; int main(int argc, char* argv[]){    DhDialog dialog;    DhOutputWindow output_window_;    //1.互相监听,注意,这里是动态添加监听,并不是互相之间直接引用各自的对象.    dialog.Attach(&output_window_);    output_window_.Attach(&dialog);    dialog.title_ = "I am infoworld";    dialog.Notify(&dialog.title_,kUpdateTitle);//通知OutputWindow    string output = "C:\\";    output_window_.Notify(&output,kUpdateOutputDir);//通知Dialog}

输出:

I am DhOutputWindow: I am infoworldI am in DhDialog: C:\


0 0