“设计模式”学习之七:解释器与中介者(行为型)

时间:2022-01-06 17:11:18

一、解释器(Interpreter)

1、引言

该模式一般用于为某种简单的特定类型的问题(如简单语言)提供一种文法,使用类来解释当中的每一条规则。

给出几种典型应用场合:正则表达式的解释与匹配、布尔表达式的操作、计算24的实例(http://www.cnblogs.com/mahope/archive/2005/05/04/149246.html)、XML格式数据解析、从大写汉字“一千零五万六千零七十二”到数字“10056072”的转换实例(http://www.cnblogs.com/MaoBisheng/archive/2008/09/08/1287014.html)等等。

可见,解释器模式应用于:较简单的文法(若复杂,则需要语法分析程序生成器);各文法规则明确独立、易于扩展;效率不是最关键因素的情况。

 

2、一般思路

下图,上下文Context会包含解释器之外的全局信息。非终结符类NonterminalExpression会递归调用终结符类TerminalExpression。客户需自行构建抽象语法树——表示某表达式,并调用解释操作Interpreter()。

 “设计模式”学习之七:解释器与中介者(行为型)

3、典型代码

基本程序代码参见《设计模式精解-GoF 23种设计模式解析附C++实现源码》即可,暂时空缺其它应用实例,待补…

 

4、应用提示

(1)Interpreter模式提供了一种很好的组织和设计简单语言文法解析器的架构

(2)Interpreter模式的缺点在于,不适于构建复杂文法的解释器。

(3)抽象语法树是一个Composite模式的实例。

(4)终结符类TerminalExpression的实例可应用Flyweight模式在抽象语法树*享。

(5)不一定要在结点类中定义解释操作Interpreter(),可应用Visitor模式将解释放入一个独立的“访问者”类,以避免在每个结点类都定义需要的几种独立的解释操作。

 

二、中介者(Mediator)

1、引言

面向对象设计鼓励将行为分布到各个对象中。中介者模式通过将各个对象间的交互封装到一个中介者对象中,从而将多对多的通信转变为一对多,降低系统复杂性,这符合OO设计中的职责单一集中的原则。

 

2、一般思路

下图,中介者Mediator/ConcreteMediator负责与同事类的对象进行通信,而具体同事ConcreteColleagueA/B无需彼此引用,只需知道中介者即可,其接口函数易于扩展。

定义抽象类Mediator是为了使各个ConcreteColleague能够与不同的中介者共同工作,当仅有唯一一个中介者时,无需定义Mediator。

 “设计模式”学习之七:解释器与中介者(行为型)

3、典型代码

参考:http://www.cnblogs.com/ywqu/archive/2010/02/09/1666196.html,实现一个简易聊天功能,聊城室就是一个中介者,参与聊天的人就是同事对象。

// "Mediator_Chatroom.h":头文件//////////////////////////

#ifndef _MEDIATOR_CHATROOM_H_
#define _MEDIATOR_CHATROOM_H_

#include <vector>
#include <iostream>
#include <conio.h>
#include <string>
using namespace std;

class AbstractColleague;

class MediatorChatroom
{
private:
vector <AbstractColleague *> vecColleague;

public:
MediatorChatroom(){}
~MediatorChatroom(){}

void Register(AbstractColleague *talker);
void Send(string from, string to, string message);
};

class AbstractColleague
{
public:
AbstractColleague(MediatorChatroom * chatroom, string strColleagueValue)
{
this->_chatroom = chatroom;
this->_strColleagueValue = strColleagueValue;
}
virtual ~AbstractColleague(){}

virtual void Receive(string from,string message)
{
cout<<"<"<<from<<"> to <"<<_strColleagueValue<<">: "<<message<<endl;
}

public:
MediatorChatroom * _chatroom;
string _strColleagueValue;

void Send(string to, string message)
{
_chatroom->Send(_strColleagueValue, to, message);
}
};

class ColleagueINer : public AbstractColleague
{
public:
ColleagueINer(MediatorChatroom * chatroom, string strColleagueValue)
:AbstractColleague(chatroom, strColleagueValue){}
~ColleagueINer(){}

void Receive(string from,string message)
{
cout<<"To one INer:";
AbstractColleague::Receive(from, message);
}
};

class ColleagueOUTer : public AbstractColleague
{
public:
ColleagueOUTer(MediatorChatroom * chatroom, string strColleagueValue)
:AbstractColleague(chatroom, strColleagueValue){}
~ColleagueOUTer(){}

void Receive(string from,string message)
{
cout<<"To one OUTer:";
AbstractColleague::Receive(from, message);
}
};

#endif //~_MEDIATOR_CHATROOM_H_


// Mediator_Chatroom.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Mediator_Chatroom.h"

void MediatorChatroom::Register(AbstractColleague *talker)
{
//引入迭代器实现按顺序访问池中的各参与者对象
vector <AbstractColleague *>:: iterator it = vecColleague.begin();
//AbstractColleague * talkerTemp;
if (vecColleague.size() == 0)//当容器内无任何对象时,先push一个对象
{
//flyTemp = new ConcreteFlyweight(key);
vecColleague.push_back(talker);
return;
}
for (; it != vecColleague.end(); it++)//遍历对象
{
string tem = talker->_strColleagueValue;
if ((*it)->_strColleagueValue == talker->_strColleagueValue)//若存在,则返回。
{
cout<<"Check <"<<talker->_strColleagueValue<<">:Ensure it used only once..."<<endl;
return;
}
//flyTemp = new ConcreteFlyweight(key);
vecColleague.push_back(talker);
return;
//return flyTemp;
}
}//

void MediatorChatroom::Send(string from, string to, string message)
{
vector <AbstractColleague *>:: iterator it = vecColleague.begin();
for (; it != vecColleague.end(); it++)//遍历对象
{
if ((*it)->_strColleagueValue == to)//若接收存在,则让其接收信息。
{
(*it)-> Receive(from, message);
return;
//cout<<"Check <"<<talker->_strColleagueValue<<">:Ensure it used only once..."<<endl;
}
else
{
//cout<<"<"<<to<<">:doesn't existed!"<<endl;
//return;
}
//flyTemp = new ConcreteFlyweight(key);
//vecColleague.push_back(talker);
//return flyTemp;
}
}

int _tmain(int argc, _TCHAR* argv[])
{
MediatorChatroom *chatroom = new MediatorChatroom;

AbstractColleague *LiLei = new ColleagueINer(chatroom, "LiLei");
AbstractColleague *HanMeimei = new ColleagueINer(chatroom, "HanMeimei");
AbstractColleague *Poly = new ColleagueINer(chatroom, "Poly");

AbstractColleague *SongJiang = new ColleagueOUTer(chatroom, "SongJiang");

chatroom->Register(LiLei);
chatroom->Register(HanMeimei);
chatroom->Register(Poly);

chatroom->Register(SongJiang);

LiLei->Send("HanMeimei", "Long time no see!");
HanMeimei->Send("LiLei", "Yepp!");
LiLei->Send("HanMeimei", "What is up? I miss U...");
HanMeimei->Send("LiLei", "Not so bad, Me2");
Poly->Send("HanMeimei", "Don't forget me!");
HanMeimei->Send("Poly", "Sorry,Bird");

LiLei->Send("SongJiang", "《Water Margin》,nice! ");

_getch();/*等待按键继续*/
return 0;
}


运行情况截图如下:

 “设计模式”学习之七:解释器与中介者(行为型)

4、应用提示

Mediator模式Colleague—Mediator之间的通信有两种方式:

一是,Colleague将自身(或其标志性成员变量)作为一个参数传递给Mediator,使其可以识别发送者;

二是,使用观察者Observer模式,将Mediator实现为一个Observer,各个Colleague作为Subject,一旦其状态改变就通知Mediator,再由Mediator将状态通知其它colleague。

本节实例采用第一种方式。第二种方式待学…