65.9K
CodeProject 正在变化。 阅读更多。
Home

内部通信模式

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.16/5 (24投票s)

2008年2月15日

CPOL

2分钟阅读

viewsIcon

34079

downloadIcon

122

定义了不同类型的类之间的多对多关系。

目录

  • 引言
  • 概述
  • 为什么选择对讲机模式?
  • 结构
  • C++ 实现
  • 典型用法

引言

对讲机模式是一种用于计算机编程的设计模式,用于观察程序中对象的状态。它与隐式调用原则相关。这种模式主要用于实现分布式事件处理系统。在某些编程语言中,此模式处理的问题由本地事件处理语法处理。这在应用程序的实时部署方面是一个非常有趣的功能。

概述

此模式的本质是一个或多个对象(称为观察者或监听器)被注册(或自行注册)以观察可能由被观察对象(主题)引发的事件。(可能引发事件的对象通常维护观察者集合。)

为什么选择对讲机模式?

我搜索了设计模式,其中我的主题和观察者可以随时更改,但我失败了。我没有找到任何设计模式,任何人都可以作为主题,而任何人都可以观察。最后,我分析了该术语,找到了解决方案。在我的模式中,任何人都可以作为主题 [通知其观察者],任何人都可以观察 [从主题接收消息]。在我的模式中,所有需要发送和接收消息的类只能从 Subject 类继承,这就足够了。

使用对讲机模式的源代码

=====================================================
#include "stdafx.h"
#include "IBaseView.h"
#include "IModel.h"

int main(int argc, char* argv[])
{
    printf("Hello Intercom!\n");

    IModel* lpModelHDD = new CModelAnalyzeHDD();
    IModel* lpModelUSB = new CModelAnalyzeUSB();

    IBaseView* lpViewTree = new CBaseViewList();
    IBaseView* lpViewList = new CBaseViewTree();

    //REGISTER FOR NOTIFICATION FROM MODEL CHANGE...
    IInterCom::getInstance()->Register(lpModelHDD,lpViewTree);
    IInterCom::getInstance()->Register(lpModelHDD,lpViewList);
    //NOTIFY ITS RELATIVE MODEL...
    IInterCom::getInstance()->Register(lpModelHDD,lpModelUSB);
    //
    IInterCom::getInstance()->Register(lpModelUSB,lpViewTree);
    IInterCom::getInstance()->Register(lpModelUSB,lpViewList);
    //NOTIFY ITS RELATIVE MODEL...
    IInterCom::getInstance()->Register(lpModelUSB,lpModelHDD);

    lpModelHDD->analyze();
    printf("\n======================");
    lpModelUSB->analyze();
    printf("\n======================");
    //NOTIFY ITS RELATIVE VIEW...AS WELL AS MODEL
    IInterCom::getInstance()->Register(lpViewTree,lpViewList);
    IInterCom::getInstance()->Register(lpViewTree,lpModelUSB);
    IInterCom::getInstance()->Register(lpViewTree,lpModelHDD);

    ((CBaseViewTree*)lpViewTree)->onClick();
    printf("\n======================");

    //NOTIFY ITS RELATIVE VIEW...AS WELL AS MODEL
    IInterCom::getInstance()->Register(lpViewList,lpViewList);
    IInterCom::getInstance()->Register(lpViewList,lpModelUSB);
    IInterCom::getInstance()->Register(lpViewList,lpModelHDD);
    ((CBaseViewList*)lpViewList)->onClick();
    printf("\n======================");

    delete lpViewList;
    delete lpViewTree;
    delete lpModelHDD;
    delete lpModelUSB;
        IInterCom::releaseInstance();
    getch();
    return 0;
}

对讲机模式类 - IInterCom.h

/===============INTERCOM CLASS=================================/
//######################################################################
//# FILENAME: IInterCom.h
//#
//# DESCRIPTION: FOR MESSAGE PASING AMONG MANY OF CLASSES.
//# USER CAN USE DIFFERENT TYPES OF MESSAGE BUT ONLY 2 onMessage,onGoodBye
//# ARE MORE ACCEPTABLE. INTERNALLY USED <OBSERVER /> PATTERN
//# AUTHOR:        Mohammad Saiful Alam (Jewel)
//# POSITION:    Senior Software Engineer
//# E-MAIL:        saiful.alam@ bjitgroup.com
//# CREATE DATE: 2008/02/1
//#
//# Copyright (c) 2007 BJIT Ltd.
//######################################################################

#ifndef _IInterCom_H_
#define _IInterCom_H_

//--------------------------------------------------------------------------------
//EXPOSE SOME EXAMPLE MESSAGE...
//USEER CAN DEFINE ANY TYPES OF MESSAGE
//THESE MESSAGE HAS TO BE USED BY Message class...

#include <VECTOR />
using namespace std;

struct BaseMessage
{
public:
    int Progress;
    int MsgType;
    int NoOfDevice;
    char* Data;
};
//--------------------------------------------------------------------------------

class Observer;
class Subject;

class Message
{
public:
    Message(Subject* sub,BaseMessage* msgData){subject = sub;Msg = msgData;};
    Subject* subject;
    BaseMessage* Msg;//ALLOW DIFFERENT TYPES OF MESSAGES...
};

class Observer
{
public:
    virtual int onMessage(const Message& m){return 0;};
    virtual int onGoodBye(){return 0;};
};
//
class Subject : public Observer//ALLOW DIFFERENT TYPES OF SUBJECTS......
{
public:
    vector<Observer*>mObservers;
};

class IInterCom
{
public:
    IInterCom();
    virtual ~IInterCom();
    static IInterCom* getInstance();
    static void releaseInstance();
    //
    void Register(Subject* subject,Observer* observer);
    //
    int Revoke(Subject* subject,Observer* observer);
    //
    int RevokeAll(Subject* subject);
    //
    int Dispatch(const Message& message);
    //
protected:
    int IsSubjectRegistered(Subject* subject);
    //
     int IsObserverRegistered(Subject* subject,Observer* observer);

private:
    static IInterCom* mpInstance;
    vector<Subject*>mSubjects;
};

对讲机模式类 - IInterCom.cpp

//######################################################################
//# FILENAME: IInterCom.cpp
//#
//# DESCRIPTION:
//#
//#
//# AUTHOR:      Mohammad Saiful Alam (Jewel)
//# POSITION:    Senior Software Engineer
//# E-MAIL:      saiful.alam@ bjitgroup.com
//# CREATE DATE: 2008/02/1
//#
//# Copyright (c) 2007 BJIT Ltd.
//######################################################################

#include "stdafx.h"
#include "IInterCom.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IInterCom* IInterCom::mpInstance = NULL;

IInterCom::IInterCom()
{
    mSubjects.clear();
}

IInterCom::~IInterCom()
{

}

IInterCom* IInterCom::getInstance()
{
    if (NULL == mpInstance)
    {
        mpInstance = new IInterCom;
    }
    return mpInstance;
}
void IInterCom::releaseInstance()
{
    if (NULL != mpInstance)
    {
        delete mpInstance;
        mpInstance = NULL;
    }
}
//
void IInterCom::Register(Subject* subject,Observer* observer)
{
    if (IsSubjectRegistered(subject) < 0 )
    {
        mSubjects.push_back(subject);
    }
    subject->mObservers.push_back(observer);
}
//
int IInterCom::Revoke(Subject* subject,Observer* observer)
{
    Observer* pObserver = NULL;
    int liSize = subject->mObservers.size();
    for (int i = 0; i< liSize; i++)
    {
        if (observer == subject->mObservers.at(i))
        {
            pObserver = subject->mObservers.at(i);
            if (pObserver)
            {
                pObserver->onGoodBye();
            }
            subject->mObservers.erase(&pObserver);
        }
    }
    return 0;
}
//
int IInterCom::RevokeAll(Subject* subject)
{
    Observer* pObserver = NULL;
    int liSize = subject->mObservers.size();
    int i = 0;
    for (int i = 0; i< liSize; i++)
    {
        pObserver = subject->mObservers.at(i);
        if (pObserver)
        {
            pObserver->onGoodBye();
        }
    }
    //
    subject->mObservers.clear();
    return 0;
}
//
int IInterCom::Dispatch(const Message& message)
{
    Subject* pSubject = NULL;
    Observer* pObserver = NULL;
    int liSize = mSubjects.size();
    for (int i = 0; i< liSize; i++)
    {
        pSubject = mSubjects.at(i);
        if (pSubject == message.subject)
        {
            int liObservers = pSubject->mObservers.size();
            for (int j = 0; j< liObservers; j++)
            {
                pObserver = pSubject->mObservers.at(j);
                pObserver->onMessage(message);
            }
        }
    }
    return 0;
}

//
int IInterCom::IsSubjectRegistered(Subject* subject)
{
    int liSize = mSubjects.size();
    for (int i = 0; i< liSize; i++)
    {
        if (subject == mSubjects.at(i))
        {
            return i;
        }
    }
    return -1;
}
//
int IInterCom::IsObserverRegistered(Subject* subject,Observer* observer)
{    
    Observer* pObserver = NULL;
    int liSize = subject->mObservers.no();
    int i = 0;
    for ( i = 0; i< liSize; i++)
    {
        pObserver = subject->mObservers.at(i);
        if (observer == pObserver)
        {
            return i;
        }
    }    
    return -1;
}

/=======================END INTERCOMCLASS==============================/

Model 类

/======================MODEL CLASS=====================================/

// IModel.h: interface for the IModel class.
//
//////////////////////////////////////////////////////////////////////
#ifndef _IModel_H_
#define _IModel_H_

#include "IInterCom.h"

//NEEDS TO COMMUNICATE WITH OTHERS
//MAY BE VIEW, MAY BE MODEL ETC...

class IModel  : public Subject
{
public:
    IModel();
    virtual ~IModel();
    virtual void analyze() = 0;
};
//

class CModelAnalyzeHDD   : public IModel
{
public:
    CModelAnalyzeHDD(){}
    virtual ~CModelAnalyzeHDD(){}
    virtual int onMessage(const Message& m);
    virtual void analyze();
};
//

class CModelAnalyzeUSB   : public IModel
{
public:
    CModelAnalyzeUSB(){}
    virtual ~CModelAnalyzeUSB(){}
    virtual int onMessage(const Message& m);
    virtual void analyze();
};
//
#endif

--------------------------------------------------------------------
// IModel.cpp: implementation of the IModel class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "IModel.h"
#include "IBaseView.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IModel::IModel()
{

}

IModel::~IModel()
{

}
//////////////////////////////////////////////////////////////////////////
//CModelAnalyzeHDD
//////////////////////////////////////////////////////////////////////////
int CModelAnalyzeHDD::onMessage(const Message& m)
{
    if (typeid(*m.subject) == typeid(CBaseViewList))
    {
        //Message from CBaseViewList
        printf("\nSubject: CBaseViewList--------Observer:CModelAnalyzeHDD");
    }
    else if (typeid(*m.subject) == typeid(CBaseViewTree))
    {
        //Message from CModelAnalyzeHDD
        printf("\nSubject: CBaseViewTree--------Observer:CModelAnalyzeHDD");
    }
    else if (typeid(*m.subject) == typeid(CModelAnalyzeUSB))
    {
        //Message from CModelAnalyzeUSB
        printf("\nSubject: CModelAnalyzeUSB--------Observer:CModelAnalyzeHDD");
    }
    return 0;
}
void CModelAnalyzeHDD::analyze()
{
    BaseMessage msg;
    msg.Data = "HDDAnalyze";
    msg.NoOfDevice = 3;
      Message m(this,&msg);
    //NOTIFY ITS REGISTERED OBSERVER...
    //THIS PART IS DONE BY INTERCOM...
    IInterCom::getInstance()->Dispatch(m);
}
//////////////////////////////////////////////////////////////////////////
//CModelAnalyzeUSB
//////////////////////////////////////////////////////////////////////////
int CModelAnalyzeUSB::onMessage(const Message& m)
{
    if (typeid(*m.subject) == typeid(CBaseViewList))
    {
        //Message from CBaseViewList
        printf("\nSubject: CBaseViewList--------Observer:CModelAnalyzeUSB");
    }
    else if (typeid(*m.subject) == typeid(CBaseViewTree))
    {
        //Message from CModelAnalyzeHDD
        printf("\nSubject: CBaseViewTree--------Observer:CModelAnalyzeUSB");
    }
    else if (typeid(*m.subject) == typeid(CModelAnalyzeHDD))
    {
        //Message from CModelAnalyzeUSB
        printf("\nSubject: CModelAnalyzeHDD--------Observer:CModelAnalyzeUSB");
    }
    return 0;
}
void CModelAnalyzeUSB::analyze()
{
    BaseMessage msg;
    msg.Data = "UsbAnalyze";
    msg.NoOfDevice = 2;
      Message m(this,&msg);
    //NOTIFY ITS REGISTERED OBSERVER...
    //THIS PART IS DONE BY INTERCOM...
    IInterCom::getInstance()->Dispatch(m);

}

视图类

/=========================================VIEW CLASS==========================/
// IBaseView.h: interface for the IBaseView class.
//
//////////////////////////////////////////////////////////////////////
#ifndef _IBaseView_H_
#define _IBaseView_H_

#include "IInterCom.h"
class IBaseView  : public Subject
{
public:
    IBaseView();
    virtual ~IBaseView();
};
//
class CBaseViewTree  : public IBaseView
{
public:
    CBaseViewTree(){};
    virtual ~CBaseViewTree(){};
    virtual int onMessage(const Message& m);
    void onClick();
};
//
class CBaseViewList  : public IBaseView
{
public:
    CBaseViewList(){};
    virtual ~CBaseViewList(){};
    virtual int onMessage(const Message& m);
    void onClick();
};
//
#endif

------------------------------------------------------------------------------------
// IBaseView.cpp: implementation of the IBaseView class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "IBaseView.h"
#include "IModel.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IBaseView::IBaseView()
{

}

IBaseView::~IBaseView()
{

}
//
void CBaseViewTree::onClick()
{
    BaseMessage msg;
    msg.Data = "Driveletter";
      Message m(this,&msg);
    //NOTIFY ITS REGISTERED OBSERVER...
    //THIS PART IS DONE BY INTERCOM...
    IInterCom::getInstance()->Dispatch(m);
}
//////////////////////////////////////////////////////////////////////////
//CBaseViewTree
//////////////////////////////////////////////////////////////////////////
int CBaseViewTree::onMessage(const Message& m)
{
    if (typeid(*m.subject) == typeid(CBaseViewList))
    {
        //Message from CBaseViewList
        printf("\nSubject: CBaseViewList--------Observer:CBaseViewTree");
    }
    else if (typeid(*m.subject) == typeid(CModelAnalyzeHDD))
    {
        //Message from CModelAnalyzeHDD
        printf("\nSubject: CModelAnalyzeHDD--------Observer:CBaseViewTree");
    }
    else if (typeid(*m.subject) == typeid(CModelAnalyzeUSB))
    {
        //Message from CModelAnalyzeUSB
        printf("\nSubject: CModelAnalyzeUSB--------Observer:CBaseViewTree");
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////////
//CBaseViewList
//////////////////////////////////////////////////////////////////////////
int CBaseViewList::onMessage(const Message& m)
{
    if (typeid(*m.subject) == typeid(CBaseViewTree))
    {
        //Message from CBaseViewTree
        printf("\nSubject: CBaseViewTree--------Observer:CBaseViewList");
    }
    else if (typeid(*m.subject) == typeid(CModelAnalyzeHDD))
    {
        //Message from CModelAnalyzeHDD
        printf("\nSubject: CModelAnalyzeHDD--------Observer:CBaseViewList");
    }
    else if (typeid(*m.subject) == typeid(CModelAnalyzeUSB))
    {
        //Message from CModelAnalyzeUSB
        printf("\nSubject: CModelAnalyzeUSB--------Observer:CBaseViewList");
    }
    return 0;
}
//
void CBaseViewList::onClick()
{
    BaseMessage msg;
    msg.Data = "Driveletter";
      Message m(this,&msg);
    //NOTIFY ITS REGISTERED OBSERVER...
    //THIS PART IS DONE BY INTERCOM...
    IInterCom::getInstance()->Dispatch(m);
}
/====================================================================

典型用法

对讲机模式的典型用法如下

  • 监听外部事件(例如用户操作)
  • 参见事件驱动编程
  • 监听对象属性值的变化

在邮件列表中,每次发生事件(新产品、聚会等)时,都会向订阅该列表的人发送消息。使用这种模式的主要原因是其简单性和主题和观察者的动态变化。对讲机模式也经常与模型-视图-控制器 (MVC) 范例相关联。在 MVC 中,对讲机模式用于在模型和视图之间创建松散耦合。通常,对模型的修改会触发对模型观察者的通知,这些观察者实际上是视图。

© . All rights reserved.