解释器模式 - 行为模式

来源:互联网 发布:敦煌古筝淘宝经销商 编辑:程序博客网 时间:2024/05/29 11:56
个人理解:    

模式类型:

    Interpreter  解释器模式 - 行为模式
    
意图:
    Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
    Map a domain to a language, the language to a grammar, and the grammar to a hierarchical object-oriented design
    给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子。

    
概述:
    在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化。在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。
    
    效率不是一个Interpreter关心的关键问题。最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种形式。例如:正则表达式通常被转换成状态机。但即使在这种情况下,如果效率不是一个关键问题,转换器仍可用Interpreter模式实现,该模式仍是有用的。
    
角色:
    抽象表达式角色(AbstractExpression): 声明一个抽象的解释操作,这个接口为所有具体表达式角色都要实现的。
    终结符表达式角色(TerminalExpression): 实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例对应不同的终结符,
    终结符就是语言中用到的基本元素,一般不能再被分解,如: x -> xa, 这里a是终结符,因为没有别的规则可以把a变成别的符号,不过x可以变成别的符号,所以x是非终结符。
    非终结符表达式角色(NonterminalExpression): 文法中的每条规则对应于一个非终结表达式, 非终结表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
    环境角色(Context):包含解释器之外的一些全局信息。

结构图:


模式的应用场景:

The Template Method pattern should be used:
- The Interpreter pattern is used exaustively in defining grammars, tokenize input and store it.
- A specific area where Interpreter can be used are the rules engines.
- The Interpreter pattern can be used to add functionality to the composite pattern.

Example 1 - Roman Numerals Convertor

The classical example fot the interpreter pattern is the one of interpreting the roman numerals. The expresion to be interpreted is a string which is put in the context. The context consists of the remaining unparsed Roman Numeral string and of the result of the numerral that are already parsed. The context is passed to one of four sub-interpreters based on the type of interpreting(Thousand, Hundred, Ten, One). This example it's using only TerminalExpressions.
The following participant classes are involved in this example: Context - keeps the current string that has to be parsed and the decimal that contains the conversion already done. Initially the context keeps the full string that has to be converted and 0 for the output decimal.

Expression - Consists of the interpret method which receives the context. Based on the current object it uses specific values for Thousand, Hundred, Ten, One and a specific multiplier.

ThousandExpression, HundredExpression, TenExpression, OneExpression (TerminalExpression) - Those classes are usued to define each specific expression. Ussualy, the TerminalExpression classes implement the interpret method. In our case the method is already defined in the base Expression class and each TerminalExpression class defines its behaviour by implmenting the abstract methods: one, four(), five(), nine(), multiplier(). It is a template method pattern.

1.Interpreter模式的应用场合是interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式。

模式的优缺点:
优点:
    (1) 易于改变和扩展文法。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
    (2) 每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
    (3) 实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。
    (4) 增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合“开闭原则”。
缺点:
    (1) 对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
    (2) 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。
    
代码(其实读UML图要比代码还要一目了然):
package com.lee.desingerPattener23.interpreter;import java.util.ArrayList;import java.util.Iterator;class Context {private String input;private int output;public Context(String input) {this.input = input;}public String getInput() {return input;}public void setInput(String input) {this.input = input;}public int getOutput() {return output;}public void setOutput(int output) {this.output = output;}}abstract class Expression {public void interpret(Context context) {if (context.getInput().length() == 0)return;if (context.getInput().startsWith(nine())) {context.setOutput(context.getOutput() + (9 * multiplier()));context.setInput(context.getInput().substring(2));} else if (context.getInput().startsWith(four())) {context.setOutput(context.getOutput() + (4 * multiplier()));context.setInput(context.getInput().substring(2));} else if (context.getInput().startsWith(five())) {context.setOutput(context.getOutput() + (5 * multiplier()));context.setInput(context.getInput().substring(1));}while (context.getInput().startsWith(one())) {context.setOutput(context.getOutput() + (1 * multiplier()));context.setInput(context.getInput().substring(1));//截取第一字符串,只剩下后面的,例:"unhappy".substring(2) returns "happy"System.out.println("context.getOutput(): "+context.getOutput() );//System.out.println("context.getInput().substring(1):"+context.getInput().substring(1));}}public abstract String one();public abstract String four();public abstract String five();public abstract String nine();public abstract int multiplier();}class ThousandExpression extends Expression {public String one() {return "M";}public String four() {return " ";}public String five() {return " ";}public String nine() {return " ";}public int multiplier() {return 1000;}}class HundredExpression extends Expression {public String one() {return "C";}public String four() {return "CD";}public String five() {return "D";}public String nine() {return "CM";}public int multiplier() {return 100;}}class TenExpression extends Expression {public String one() {return "X";}public String four() {return "XL";}public String five() {return "L";}public String nine() {return "XC";}public int multiplier() {return 10;}}class OneExpression extends Expression {public String one() {return "I";}public String four() {return "IV";}public String five() {return "V";}public String nine() {return "IX";}public int multiplier() {return 1;}}public class MainInterpreter {public static void main(String[] args) {String roman = "MCMXXVIII";Context context = new Context(roman);// Build the 'parse tree'ArrayList<Expression> tree = new ArrayList<Expression>();tree.add(new ThousandExpression());tree.add(new HundredExpression());tree.add(new TenExpression());tree.add(new OneExpression());// Interpretfor (Iterator it = tree.iterator(); it.hasNext();) {Expression exp = (Expression) it.next();exp.interpret(context);}System.out.println(roman + " = "+ Integer.toString(context.getOutput()));}}


所有模式:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
补充模式:空对象模式


参考/转自:
http://www.oodesign.com/interpreter-pattern.html
http://blog.csdn.net/ylchou/article/details/7594135
http://blog.csdn.net/lcl_data/article/details/9259905

转载请注明:http://blog.csdn.net/paincupid/article/details/46991977

0 0