`
oraclestudy
  • 浏览: 482336 次
文章分类
社区版块
存档分类

Interpreter设计模式

 
阅读更多
在软件构建过程中,若果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变
化。在这种情况下,将特定领域的问题表达为某种语法规则下的句子,再构建一个解释器来解释这样的句子,从而达到解决问题的目的。
给定一个语言,定义他的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 -GoF
Interpreter设计模式中的几种角色:
AbstractExpression: 
- Declares an abstract Interpret operation that is common to all nodes in the abstract syntax tree.
TerminalExpression:
- Implements an Interpret operation associated with terminal symbols in the grammer.
- An instance is required for every terminal symbol in a sentence.
NonterminalExpression:
The other inherited class / implementation of the AbstractExpression abstract class / interface, intended ofr the nonterminal
nodes in the grammar and syntax tree. It keeps a reference to the next AbstractExpression(s) and invokes the interpret 
method on each of its children.
- One such class is required for every rule R ::= R1R2…Rn in the grammer.
- Maintains instance variables of type AbstractExpression for each of the symbols R1 throught Rn.
- Implements an Interpret operation for nonterminal symbols in the grammar. Interpret typically calls itself recursively on the 
  variables representing R1 through Rn.
Context:
Container for the information that is needed in several places in the interpreter. It can serve as a communication channel among
serveral AbstractExpresssion instances.
- Contains information that’s global to the interpreter. 
PatternClient:
Either builds or receives an instance of an abstract syntax tree. This syntax tree is composed of instances of 
TerminalExpressions and NonterminalExpression to model a specific sentence. The PatternClient invokes the 
interpret method with the appropriate context where necessary.
Interpreter模式的应用场合是interpreter模式应用中的难点,只有满足"业务规则频繁变化,且类似的模式不断重复出现,并且容易抽
象为语法规则的问题"才适合使用Interpreter模式。
使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法。
 
Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,这时候就不应该采用
Interpreter模式了。
效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种形式。例如:正则
表达式通常被转换成状态机。但即使在这种情况下,转换器仍可用解释器模式实现,该模式仍是有用的。
下面是一个将中文数字转换成阿拉伯数字的例子,其中用到了Interpreter
// Context.java
package com.pnft.patterns.interpreter;
public class Context
{
 private String statement;
 private long data;
 
 public Context(String statement)
 {
 this.statement = statement;
 }
 public String getStatement()
 {
 return statement;
 }
 public void setStatement(String statement)
 {
 this.statement = statement;
 }
 public long getData()
 {
 return data;
 }
 public void setData(long data)
 {
 this.data = data;
 }
}
// Expression.java
package com.pnft.patterns.interpreter;
import java.util.Hashtable;
public abstract class Expression
{
 protected Hashtable<String, Integer> dictionary = new Hashtable<String, Integer>();
 
 public Expression()
 {
 dictionary.put("", 1);
 dictionary.put("", 2);
 dictionary.put("", 3);
 dictionary.put("", 4);
 dictionary.put("", 5);
 dictionary.put("", 6);
 dictionary.put("", 7);
 dictionary.put("", 8);
 dictionary.put("", 9);
 }
 
 public void Interpret(Context ctx)
 { 
 if(ctx.getStatement().length() == 0)
 {
 // 处理完成,返回
 return;
 }
 else if(ctx.getStatement().endsWith(""))
 {
 String tempstr = ctx.getStatement();
 tempstr = tempstr.substring(0, tempstr.length() - 1);
 ctx.setStatement(tempstr);
 return;
 }
 else
 {
 for(String key : dictionary.keySet())// 相当于C#中的foreach
 {
 int value = ((Integer)dictionary.get(key)).intValue();
 if(ctx.getStatement().endsWith(key + GetPostfix()))
 {
  long tempdata = ctx.getData();
 tempdata += value * Multiplier();
 ctx.setData(tempdata);
 
 String tempstr = ctx.getStatement();
 tempstr = tempstr.substring(0, tempstr.length() - this.GetLength());
 ctx.setStatement(tempstr);
  
 return;
 }
 }
 }
 }
 public abstract String GetPostfix();
 public abstract int Multiplier();
 public int GetLength()
 {
 return this.GetPostfix().length() + 1;
 }
}
// GeExpression.java
package com.pnft.patterns.interpreter;
public class GeExpression extends Expression
{
 @Override
 public String GetPostfix()
 {
 return "";
 }
 @Override
 public int Multiplier()
 {
 return 1;
 }
 
 @Override
 public int GetLength()
 {
 return 1;
 }
}
// ShExpression.java
package com.pnft.patterns.interpreter;
public class ShExpression extends Expression
{
 @Override
 public String GetPostfix()
 {
 return "";
 }
 @Override
 public int Multiplier()
 {
 return 10;
 }
}
// BaExpression.java
package com.pnft.patterns.interpreter;
public class BaExpression extends Expression
{
 @Override
 public String GetPostfix()
 {
 return "";
 }
 @Override
 public int Multiplier()
 {
 return 100;
 }
}
// QiExpression.java
package com.pnft.patterns.interpreter;
public class QiExpression extends Expression
{
 @Override
 public String GetPostfix()
 {
 return "";
 }
 @Override
 public int Multiplier()
 {
 return 1000;
 }
}
// WaExpression.java
package com.pnft.patterns.interpreter;
import java.util.ArrayList;
public class WaExpression extends Expression
{
 @Override
 public String GetPostfix()
 {
 return "";
 }
 @Override
 public int Multiplier()
 {
 return 10000;
 }
 @Override
 public void Interpret(Context ctx)
 {
 if(ctx.getStatement().endsWith(""))
 {
 String tempstr = ctx.getStatement();
 tempstr = tempstr.substring(0, tempstr.length() - 1);
 ctx.setStatement(tempstr);
 
 return;
 }
 
 if(ctx.getStatement().length() == 0)
 {
 // 处理完成,返回
 return;
 }
 else
 {
 ArrayList<Expression> stxTree = new ArrayList<Expression>();
 stxTree.add(new GeExpression());
 stxTree.add(new ShExpression());
 stxTree.add(new BaExpression());
 stxTree.add(new QiExpression());
 
 if(ctx.getStatement().endsWith(GetPostfix()))
 {
 long tempdata = ctx.getData();
 ctx.setData(0);
 
 String tempstr = ctx.getStatement();
 tempstr = tempstr.substring(0, tempstr.length() - 1);
 ctx.setStatement(tempstr);
 
 for(Expression exp : stxTree)
 {
 exp.Interpret(ctx);
 }
 
 ctx.setData(tempdata + ctx.getData() * this.Multiplier());
 
 return;
 }
 }
 }
}
// YiExpression.java
package com.pnft.patterns.interpreter;
import java.util.ArrayList;
public class YiExpression extends Expression
{
 @Override
 public String GetPostfix()
 {
 return "亿";
 }
 @Override
 public int Multiplier()
 {
 return 100000000;
 }
 @Override
 public void Interpret(Context ctx)
 {
 if(ctx.getStatement().endsWith(""))
 {
 String tempstr = ctx.getStatement();
 tempstr = tempstr.substring(0, tempstr.length() - 1);
 ctx.setStatement(tempstr);
 
 return;
 }
 
 if(ctx.getStatement().length() == 0)
 {
 // 处理完成,返回
 return;
 }
 else
 {
 ArrayList<Expression> stxTree = new ArrayList<Expression>();
 stxTree.add(new GeExpression());
 stxTree.add(new ShExpression());
 stxTree.add(new BaExpression());
 stxTree.add(new QiExpression());
 stxTree.add(new WaExpression());
 
 if(ctx.getStatement().endsWith(GetPostfix()))
 {
 long tempdata = ctx.getData();
 ctx.setData(0);
 
 String tempstr = ctx.getStatement();
 tempstr = tempstr.substring(0, tempstr.length() - 1);
 ctx.setStatement(tempstr);
 
 for(Expression exp : stxTree)
 {
 exp.Interpret(ctx);
 }
 
 ctx.setData(tempdata + ctx.getData() * this.Multiplier());
 
 return;
 }
 }
 }
}
// PatternClient.java
package com.pnft.patterns.interpreter;
import java.util.ArrayList;
public class PatternClient
{
 public static void main(String[] args)
 {
 String chineseNumber = "九万六千六百八十九亿零七百三十一万六千八百三十九";
 Context ctx = new Context(chineseNumber);
 
 // 构造语法树
 ArrayList<Expression> syntaxTree = new ArrayList<Expression>();
 syntaxTree.add(new GeExpression());
 syntaxTree.add(new ShExpression());
 syntaxTree.add(new BaExpression());
 syntaxTree.add(new QiExpression());
 syntaxTree.add(new WaExpression());
 syntaxTree.add(new YiExpression());
 
 // 开始解释
 for(Expression exp : syntaxTree)
 {
 exp.Interpret(ctx);
 }
 
 System.out.println(chineseNumber + " = " + ctx.getData());
 }
}
上述代码运行结果:
九万六千六百八十九亿零七百三十一万六千八百三十九 = 9668907316839
上述代码对应静态UML类图:
上述程序的实际运算步骤:
"九万六千六百八十九亿零七百三十一万六千八百三十九"  ctx.data = 0
"九万六千六百八十九亿零七百三十一万六千八百三十" ctx.data = 9
"九万六千六百八十九亿零七百三十一万六千八百" ctx.data = 39
"九万六千六百八十九亿零七百三十一万六千" ctx.data = 839
"九万六千六百八十九亿零七百三十一万" ctx.data = 6839 (""去掉)
"九万六千六百八十九亿零七百三十一" ctx.data = 6839 ("零七百三十一"将递归地使用前面已有的Expression)
"九万六千六百八十九亿" ctx.data = 7316839 ("亿"去掉)
"九万六千六百八十九" ctx.data = 7316839 ("九万六千六百八十九"将递归地使用前面已有的Expression)
 ctx.data = 9668907316839
分享到:
评论

相关推荐

    C++设计模式课件25_Interpreter.pdf

    C++设计模式课件25_Interpreter.pdfC++设计模式课件25_Interpreter.pdf

    (行为型模式) Interpreter 解释器模式

    C#面向对象设计模式 (行为型模式) Interpreter 解释器模式 视频讲座下载

    Interpreter模式

    23种设计模式的java实现之Interpreter,代码实现

    JAVA设计模式chm文档

    创建模式: 设计模式之Factory 设计模式之Prototype(原型) 设计模式之Builder 设计模式之Singleton(单态) 结构模式: 设计模式之Facade(外观) 设计模式之Proxy(代理) ...设计模式之Interpreter(解释器) 设计模式之Visitor

    Java设计模式 设计模式介绍

    章节介绍:1、爪哇语言结构性模式之变压器模式介绍 2、爪哇语言抽象工厂创立性模式介绍 3、工厂方法创立...10、设计模式之State 11、设计模式之Facade(外观) 12、设计模式之Interpreter(解释器) 13、设计模式之Visitor

    设计模式精解-GoF 23种设计模式解析附C++实现源码

    写完了Interpreter模式之后,我习惯性的看看下一天的安排,却陡然发现GoF的23个设计模式的解析已经在我不经意间写完了。就像在一年前看GoF的《设计模式》一书,和半年前用C++模拟、实现23种经典的设计模式一般,透过...

    C++ Interpreter模式

    23种设计模式之二十三(行为模式)Interpreter模式

    设计模式文档 chm

    设计模式参考文档 创建模式: 设计模式之Factory 设计模式之Prototype(原型) 设计模式之Builder 设计模式之Singleton(单态) 结构模式: 设计模式之Facade(外观) ...设计模式之Interpreter(解释器) 设计模式之Visitor

    设计模式之解释器模式(Interpreter)

    解释器模式(Interpreter) 用意:定义一种语言,定义它的方法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

    尚硅谷设计模式源码笔记课件.zip

    本课程针对上述问题,有针对性的进行了升级 (1) 授课方式采用 图解+框架源码分析的方式,让课程生动有趣好理解 (2) 系统全面的讲解了设计模式,包括 设计模式七大原则、UML类图-类的六大关系、23种设计模式及其分类,...

    C#面向对象设计模式纵横谈(视频与源码)

    C#面向对象设计模式纵横谈(16):(行为型模式) Interpreter 解释器模式 C#面向对象设计模式纵横谈(17):(行为型模式) Mediator 中介者模式 C#面向对象设计模式纵横谈(18):(行为型模式) Iterator 迭代器模式 C#...

    研磨设计模式(完整带书签).part2.pdf

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    设计模式精解-GoF 23种设计模式解析

    设计模式精解-GoF 23 种设计模式解析附 C++实现源码 目 录 引 言 0.1 设计模式解析(总序) 0.2 设计模式解析后记 0.3 与作者联系 1 创建型模式 1.1 Factory模式 1.2 AbstactFactory模式 1.3 Singleton...

    Head First设计模式

    至于第14章则很快地浏览尚未介绍的设计模式,包括Bridge、Builder、ChainofResponsibility、Flyweight、Interpreter、Mediator、Memento、Prototype,Visitor。第1章还介绍了四个基本概念(抽象、封装、继承、多态),...

    HeadFirst设计模式(中文版)

    至于第14章则很快地浏览尚未介绍的设计模式,包括Bridge、Builder、Chain of Responsibility、Flyweight、Interpreter、Mediator、Memento、Prototype,Visitor。第1章还介绍了四个○○基本概念(抽象、封装、继承、...

    C#面向对象设计模式纵横谈(16):(行为型模式) Interpreter 解释器模式 (Level 300)

    C#面向对象设计模式纵横谈(16):(行为型模式) Interpreter 解释器模式 (Level 300)

    大优惠Head First 设计模式

    至于第14章则很快地浏览尚未介绍的设计模式,包括Bridge、Builder、Chain of Responsibility、Flyweight、Interpreter、Mediator、Memento、Prototype,Visitor。第1章还介绍了四个○○基本概念(抽象、封装、继承、...

    head first 设计模式

    至于第14章则很快地浏览尚未介绍的设计模式,包括Bridge、Builder、Chain of Responsibility、Flyweight、Interpreter、Mediator、Memento、Prototype,Visitor。第1章还介绍了四个OO基本概念(抽象、封装、继承、...

    C#面向对象设计模式纵横谈\16 行为型模式Interpreter解释器模式.zip

    在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要资源分。敬请期待。 这是第16节:行为型...

    Head First 设计模式(中文版)

    至于第14章则很快地浏览尚未介绍的设计模式,包括Bridge、Builder、Chain of Responsibility、Flyweight、Interpreter、Mediator、Memento、Prototype,Visitor。第1章还介绍了四个○○基本概念(抽象、封装、继承、...

Global site tag (gtag.js) - Google Analytics