Windows CE 2.10Windows CE .NET 4.1Windows CE .NET 4.2Windows CE 3.0Windows CE .NET 4.0Windows CE 2.11Windows XP Tablet Ed.嵌入式Windows MobileVisual C++ 7.1Visual C++ 8.0Windows VistaVisual C++ 7.0C++/CLIWindows 2003Windows 2000设计 / 图形Visual C++ 6.0架构Windows XP中级WindowsC++
内部通信模式






2.16/5 (24投票s)
定义了不同类型的类之间的多对多关系。

目录
- 引言
- 概述
- 为什么选择对讲机模式?
- 结构
- 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 中,对讲机模式用于在模型和视图之间创建松散耦合。通常,对模型的修改会触发对模型观察者的通知,这些观察者实际上是视图。