电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

老生常谈:解释器模式


发布日期:2022/10/14
 
解释器模式的目的:

如果某一类问题一再的发生此时比较好的做法是将此类问题的各个实例表达为一个简单语言中的语句这样可以建造一个解释器通过解释这些语句达到解决问题的目的

解释器模式的定义

定义语言的文法并且建立一个解释器来解释该语言中的句子它属于类的行为模式这里的语言意思是使用规定格式和语法的代码

示意案例:

解释器这个模式在实际应用当中应用并不广泛能想到的例子也不多可能是我水平不够这里我拿一个把大写数字输出为阿拉伯数字数字的需求来用解释器模式实现例如

:伍千肆百参拾贰输出为

:当用户输入的是数字字符串时直接输入数字例如直接输出

解释器模式的结构

模式所涉及的角色

:抽象表达式角色声明一个所有的具体表达式角色都需要实现的抽象接口这个接口主要是一个interprect方法我们叫解释方法

注意本示例中的抽象表达式角色中的解释方法并非抽象方法因为这个案例特殊数字解释的方法过程一样

///<summary>

///抽象表达式角色

///</summary>

publicabstractclassExpression

{

///<summary>

///汉字数字与阿拉伯数字数字的对应字典

///</summary>

protectedDictionary<stringint>table=newDictionary<stringint>();

publicExpression()

{

tableAdd();

tableAdd();

tableAdd();

tableAdd();

tableAdd();

tableAdd();

tableAdd();

tableAdd();

tableAdd();

}

///<summary>

///所有的具体表达式角色都需要实现的抽象方法

///这个方法为虚方法并非抽象方法为了代码复用

///</summary>

///<paramname=context>环境角色</param>

publicvirtualvoidInterpret(Contextcontext)

{

//如果要处理的字符串长度为则返回

if(contextstatementLength==)

{

return;

}

foreach(stringkeyintableKeys)

{

intvalue=table[key];

if(contextstatementEndsWith(key+GetPostifix()))

{

contextdata+=value*Multiplier();

contextstatement=contextstatementSubstring(contextstatementLengththisGetLength());

break;

}

if(contextstatementEndsWith())

{

contextstatement=contextstatementSubstring(contextstatementLength);

break;

}

if(contextstatementLength==)

{

return;

}

}

}

///<summary>

///取汉字数字单位

///个位数为空

///十位数为十

///百位数为百

///千位数为千

///</summary>

///<returns></returns>

publicabstractstringGetPostifix();

///<summary>

///例如:个位上数字为则最后为*

///例如:百位上数字为则表示*

///</summary>

///<returns></returns>

publicabstractintMultiplier();

///<summary>

///例如:个位的长度为一位

///例如数字三十表示两位

///例如四百表示两位

///</summary>

///<returns></returns>

publicvirtualintGetLength()

{

returnthisGetPostifix()Length+;

}

}

终结符表达式角色一个具体角色

>实现了抽象表达式角色所要求的接口主要是interpret方法

>:方法中的每一个终结符都有一个具体终结表达式与之相对应

说明如果用户输入的内容不是汉字而是数字字符串则直接输出不必解释

///<summary>

///终结符表达式角色

///如果能换算成数字则直接换算后返回

///</summary>

classTerminalExpression:Expression

{

///<summary>

///重写解释方法

///</summary>

///<paramname=context>环境角色</param>

publicoverridevoidInterpret(Contextcontext)

{

inti=;

try

{

i=intParse(contextstatement);

//如果是数字则说明能够直接转换

//也就是说用不到非终结表达式角色

contextstatement=;

contextdata=i;

}

catch

{

//说明输入的是汉字数字不做任何处理

}

}

publicoverridestringGetPostifix()

{

return;

}

publicoverrideintMultiplier(){return;}

}

非终结符表达式角色这也是一个具体角色

>:文法中的每一条规则R=RRRn都需要一个具体的非终结符表达式类;

>:对每一个RR中的符号都持有一个静态类型为Expression的实例变量;

>:实现解释操作解释操作以递归的方式调用上面所提到的代表RR中的各个符号的实例变量

注意本示例中由于解释的方法都一样为些非终结符表达中的解释方法在没有重写的情况下调用抽象表达式角色的解释方法

///<summary>

///非终结表达式角色

///解释个位数

///</summary>

publicclassNonterminalOneExpression:Expression

{

publicoverridestringGetPostifix()

{

return;

}

publicoverrideintMultiplier(){return;}

publicoverrideintGetLength()

{

return;

}

}

///<summary>

///非终结表达式角色

///解释十位数

///</summary>

publicclassNonterminalTenExpression:Expression

{

publicoverridestringGetPostifix()

{

return;

}

publicoverrideintMultiplier(){return;}

publicoverrideintGetLength()

{

return;

}

}

///<summary>

///非终结表达式角色

///解释百位数

///</summary>

publicclassNonterminalHundredExpression:Expression

{

publicoverridestringGetPostifix()

{

return;

}

publicoverrideintMultiplier(){return;}

publicoverrideintGetLength()

{

return;

}

}

///<summary>

///非终结表达式角色

///解释千位数

///</summary>

publicclassNonterminalThousandExpression:Expression

{

publicoverridestringGetPostifix()

{

return;

}

publicoverrideintMultiplier(){return;}

publicoverrideintGetLength()

{

return;

}

}

客户端角色

>:建造一个抽象语法树;抽象语法树的每一个节点都代表一个语句而在每一个节点上都可以执行解释方法这个方法的执行就代表这个语句的解释

>:调用解释操作

stringroman=伍千肆百参拾贰;//

Contextcontext=newContext(roman);

//构造抽象语法树

ArrayListtree=newArrayList();

//加入终结符表达式

//如果能直接转换成数字则直接返回

treeAdd(newTerminalExpression());

//非终结符处理个位数

treeAdd(newNonterminalOneExpression());

//非终结符处理十位数

treeAdd(newNonterminalTenExpression());

//非终结符处理百位数

treeAdd(newNonterminalHundredExpression());

//非终结器处理千位数

treeAdd(newNonterminalThousandExpression());

//对抽象语法树的每个枝节进行解释操作

foreach(Expressionexpintree)

{

expInterpret(context);

}

ConsoleWriteLine({}={}romancontextdata);

环境角色提供解释器之外的一些全局信息比如变量的真实量值

///<summary>

///环境角色

///</summary>

publicclassContext

{

///<summary>

///汉字表示的数字

///</summary>

publicstringstatement

{

get;

set;

}

///<summary>

///阿拉伯数字

///</summary>

publicintdata

{

get;

set;

}

///<summary>

///构造函数

///接受一个汉字表达式数字

///</summary>

///<paramname=statement>汉字表达式数字</param>

publicContext(stringstatement)

{

thisstatement=statement;

}

}

解释器模式适用性

系统有一个简单的语言可供解释

一些重复发生的问题可以用这种简单的语言表达

效率不是主要的考虑

上一篇:利用脚本做的图片来回滑动

下一篇:限制文本框的输入(只输入数字)