《JAVA與模式》第25天—解釋器模式 – JAVA編程語言程序開發技術文章

解釋器模式是類的行為模式。給定一個語言之後,解釋器模式可以定義出其文法的一種表示,並同時提供一個解釋器。客戶端可以使用這個解釋器來解釋這個語言中的句子。

解釋器模式的結構

  下面就以一個示意性的系統為例,討論解釋器模式的結構。系統的結構圖如下所示:

 

  模式所涉及的角色如下所示:

  (1)抽象表達式(Expression)角色:聲明一個所有的具體表達式角色都需要實現的抽象接口。這個接口主要是一個interpret()方法,稱做解釋操作。

  (2)終結符表達式(Terminal Expression)角色:實現瞭抽象表達式角色所要求的接口,主要是一個interpret()方法;文法中的每一個終結符都有一個具體終結表達式與之相對應。比如有一個簡單的公式R=R1+R2,在裡面R1和R2就是終結符,對應的解析R1和R2的解釋器就是終結符表達式。

  (3)非終結符表達式(Nonterminal Expression)角色:文法中的每一條規則都需要一個具體的非終結符表達式,非終結符表達式一般是文法中的運算符或者其他關鍵字,比如公式R=R1+R2中,“+"就是非終結符,解析“+”的解釋器就是一個非終結符表達式。

  (4)環境(Context)角色:這個角色的任務一般是用來存放文法中各個終結符所對應的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些信息需要存放到環境角色中,很多情況下我們使用Map來充當環境角色就足夠瞭。

 

  為瞭說明解釋器模式的實現辦法,這裡給出一個最簡單的文法和對應的解釋器模式的實現,這就是模擬Java語言中對佈爾表達式進行操作和求值。

  在這個語言中終結符是佈爾變量,也就是常量true和false。非終結符表達式包含運算符and,or和not等佈爾表達式。這個簡單的文法如下:

    Expression    ::= Constant | Variable | Or | And | Not

    And     ::= Expression 'AND' Expression

    Or     ::= Expression 'OR' Expression

    Not       ::= 'NOT' Expression

    Variable   ::= 任何標識符

    Constant         ::= 'true' | 'false'

  解釋器模式的結構圖如下所示:

 

 

  源代碼
  抽象表達式角色

[java] 
package com.bankht.Interpreter; 
 
/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:08:58
 * 
 * @類說明 :抽象表達式角色
 */ 
public abstract class Expression { 
    /**
     * 以環境為準,本方法解釋給定的任何一個表達式
     */ 
    public abstract boolean interpret(Context ctx); 
 
    /**
     * 檢驗兩個表達式在結構上是否相同
     */ 
    public abstract boolean equals(Object obj); 
 
    /**
     * 返回表達式的hash code
     */ 
    public abstract int hashCode(); 
 
    /**
     * 將表達式轉換成字符串
     */ 
    public abstract String toString(); 

package com.bankht.Interpreter;

/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:08:58
 *
 * @類說明 :抽象表達式角色
 */
public abstract class Expression {
 /**
  * 以環境為準,本方法解釋給定的任何一個表達式
  */
 public abstract boolean interpret(Context ctx);

 /**
  * 檢驗兩個表達式在結構上是否相同
  */
 public abstract boolean equals(Object obj);

 /**
  * 返回表達式的hash code
  */
 public abstract int hashCode();

 /**
  * 將表達式轉換成字符串
  */
 public abstract String toString();
}

  一個Constant對象代表一個佈爾常量

[java] 
package com.bankht.Interpreter; 
 
/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:09:35
 * 
 * @類說明 :一個Constant對象代表一個佈爾常量
 */ 
public class Constant extends Expression { 
 
    private boolean value; 
 
    public Constant(boolean value) { 
        this.value = value; 
    } 
 
    @Override 
    public boolean equals(Object obj) { 
 
        if (obj != null && obj instanceof Constant) { 
            return this.value == ((Constant) obj).value; 
        } 
        return false; 
    } 
 
    @Override 
    public int hashCode() { 
        return this.toString().hashCode(); 
    } 
 
    @Override 
    public boolean interpret(Context ctx) { 
 
        return value; 
    } 
 
    @Override 
    public String toString() { 
        return new Boolean(value).toString(); 
    } 
 

package com.bankht.Interpreter;

/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:09:35
 *
 * @類說明 :一個Constant對象代表一個佈爾常量
 */
public class Constant extends Expression {

 private boolean value;

 public Constant(boolean value) {
  this.value = value;
 }

 @Override
 public boolean equals(Object obj) {

  if (obj != null && obj instanceof Constant) {
   return this.value == ((Constant) obj).value;
  }
  return false;
 }

 @Override
 public int hashCode() {
  return this.toString().hashCode();
 }

 @Override
 public boolean interpret(Context ctx) {

  return value;
 }

 @Override
 public String toString() {
  return new Boolean(value).toString();
 }

}

  一個Variable對象代表一個有名變量

[java] 
package com.bankht.Interpreter; 
 
/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:10:16
 * 
 * @類說明 :一個Variable對象代表一個有名變量
 */ 
public class Variable extends Expression { 
 
    private String name; 
 
    public Variable(String name) { 
        this.name = name; 
    } 
 
    @Override 
    public boolean equals(Object obj) { 
 
        if (obj != null && obj instanceof Variable) { 
            return this.name.equals(((Variable) obj).name); 
        } 
        return false; 
    } 
 
    @Override 
    public int hashCode() { 
        return this.toString().hashCode(); 
    } 
 
    @Override 
    public String toString() { 
        return name; 
    } 
 
    @Override 
    public boolean interpret(Context ctx) { 
        return ctx.lookup(this); 
    } 
 

package com.bankht.Interpreter;

/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:10:16
 *
 * @類說明 :一個Variable對象代表一個有名變量
 */
public class Variable extends Expression {

 private String name;

 public Variable(String name) {
  this.name = name;
 }

 @Override
 public boolean equals(Object obj) {

  if (obj != null && obj instanceof Variable) {
   return this.name.equals(((Variable) obj).name);
  }
  return false;
 }

 @Override
 public int hashCode() {
  return this.toString().hashCode();
 }

 @Override
 public String toString() {
  return name;
 }

 @Override
 public boolean interpret(Context ctx) {
  return ctx.lookup(this);
 }

}
 

  代表邏輯“與”操作的And類,表示由兩個佈爾表達式通過邏輯“與”操作給出一個新的佈爾表達式的操作

[java]
package com.bankht.Interpreter; 
 
/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:10:55
 * 
 * @類說明 :代表邏輯“與”操作的And類,表示由兩個佈爾表達式通過邏輯“與”操作給出一個新的佈爾表達式的操作
 */ 
public class And extends Expression { 
 
    private Expression left, right; 
 
    public And(Expression left, Expression right) { 
        this.left = left; 
        this.right = right; 
    } 
 
    @Override 
    public boolean equals(Object obj) { 
        if (obj != null && obj instanceof And) { 
            return left.equals(((And) obj).left) && right.equals(((And) obj).right); 
        } 
        return false; 
    } 
 
    @Override 
    public int hashCode() { 
        return this.toString().hashCode(); 
    } 
 
    @Override 
    public boolean interpret(Context ctx) { 
 
        return left.interpret(ctx) && right.interpret(ctx); 
    } 
 
    @Override 
    public String toString() { 
        return "(" + left.toString() + " AND " + right.toString() + ")"; 
    } 
 

package com.bankht.Interpreter;

/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:10:55
 *
 * @類說明 :代表邏輯“與”操作的And類,表示由兩個佈爾表達式通過邏輯“與”操作給出一個新的佈爾表達式的操作
 */
public class And extends Expression {

 private Expression left, right;

 public And(Expression left, Expression right) {
  this.left = left;
  this.right = right;
 }

 @Override
 public boolean equals(Object obj) {
  if (obj != null && obj instanceof And) {
   return left.equals(((And) obj).left) && right.equals(((And) obj).right);
  }
  return false;
 }

 @Override
 public int hashCode() {
  return this.toString().hashCode();
 }

 @Override
 public boolean interpret(Context ctx) {

  return left.interpret(ctx) && right.interpret(ctx);
 }

 @Override
 public String toString() {
  return "(" + left.toString() + " AND " + right.toString() + ")";
 }

}

  代表邏輯“或”操作的Or類,代表由兩個佈爾表達式通過邏輯“或”操作給出一個新的佈爾表達式的操作

[java] 
package com.bankht.Interpreter; 
 
/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:11:20
 * 
 * @類說明 :代表邏輯“或”操作的Or類,代表由兩個佈爾表達式通過邏輯“或”操作給出一個新的佈爾表達式的操作
 */ 
public class Or extends Expression { 
    private Expression left, right; 
 
    public Or(Expression left, Expression right) { 
        this.left = left; 
        this.right = right; 
    } 
 
    @Override 
    public boolean equals(Object obj) { 
        if (obj != null && obj instanceof Or) { 
            return this.left.equals(((Or) obj).left) && this.right.equals(((Or) obj).right); 
        } 
        return false; 
    } 
 
    @Override 
    public int hashCode() { 
        return this.toString().hashCode(); 
    } 
 
    @Override 
    public boolean interpret(Context ctx) { 
        return left.interpret(ctx) || right.interpret(ctx); 
    } 
 
    @Override 
    public String toString() { 
        return "(" + left.toString() + " OR " + right.toString() + ")"; 
    } 
 

package com.bankht.Interpreter;

/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:11:20
 *
 * @類說明 :代表邏輯“或”操作的Or類,代表由兩個佈爾表達式通過邏輯“或”操作給出一個新的佈爾表達式的操作
 */
public class Or extends Expression {
 private Expression left, right;

 public Or(Expression left, Expression right) {
  this.left = left;
  this.right = right;
 }

 @Override
 public boolean equals(Object obj) {
  if (obj != null && obj instanceof Or) {
   return this.left.equals(((Or) obj).left) && this.right.equals(((Or) obj).right);
  }
  return false;
 }

 @Override
 public int hashCode() {
  return this.toString().hashCode();
 }

 @Override
 public boolean interpret(Context ctx) {
  return left.interpret(ctx) || right.interpret(ctx);
 }

 @Override
 public String toString() {
  return "(" + left.toString() + " OR " + right.toString() + ")";
 }

}

  代表邏輯“非”操作的Not類,代表由一個佈爾表達式通過邏輯“非”操作給出一個新的佈爾表達式的操作

[java]
package com.bankht.Interpreter; 
 
/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:11:36
 * 
 * @類說明 :代表邏輯“非”操作的Not類,代表由一個佈爾表達式通過邏輯“非”操作給出一個新的佈爾表達式的操作
 */ 
public class Not extends Expression { 
 
    private Expression exp; 
 
    public Not(Expression exp) { 
        this.exp = exp; 
    } 
 
    @Override 
    public boolean equals(Object obj) { 
        if (obj != null && obj instanceof Not) { 
            return exp.equals(((Not) obj).exp); 
        } 
        return false; 
    } 
 
    @Override 
    public int hashCode() { 
        return this.toString().hashCode(); 
    } 
 
    @Override 
    public boolean interpret(Context ctx) { 
        return !exp.interpret(ctx); 
    } 
 
    @Override 
    public String toString() { 
        return "(Not " + exp.toString() + ")"; 
    } 
 

package com.bankht.Interpreter;

/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:11:36
 *
 * @類說明 :代表邏輯“非”操作的Not類,代表由一個佈爾表達式通過邏輯“非”操作給出一個新的佈爾表達式的操作
 */
public class Not extends Expression {

 private Expression exp;

 public Not(Expression exp) {
  this.exp = exp;
 }

 @Override
 public boolean equals(Object obj) {
  if (obj != null && obj instanceof Not) {
   return exp.equals(((Not) obj).exp);
  }
  return false;
 }

 @Override
 public int hashCode() {
  return this.toString().hashCode();
 }

 @Override
 public boolean interpret(Context ctx) {
  return !exp.interpret(ctx);
 }

 @Override
 public String toString() {
  return "(Not " + exp.toString() + ")";
 }

}
 

 

  環境(Context)類定義出從變量到佈爾值的一個映射

 

[java] 
package com.bankht.Interpreter; 
 
import java.util.HashMap; 
import java.util.Map; 
 
/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:11:54
 * 
 * @類說明 :環境(Context)類定義出從變量到佈爾值的一個映射
 */ 
public class Context { 
 
    private Map<Variable, Boolean> map = new HashMap<Variable, Boolean>(); 
 
    public void assign(Variable var, boolean value) { 
        map.put(var, new Boolean(value)); 
    } 
 
    public boolean lookup(Variable var) throws IllegalArgumentException { 
        Boolean value = map.get(var); 
        if (value == null) { 
            throw new IllegalArgumentException(); 
        } 
        return value.booleanValue(); 
    } 

package com.bankht.Interpreter;

import java.util.HashMap;
import java.util.Map;

/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:11:54
 *
 * @類說明 :環境(Context)類定義出從變量到佈爾值的一個映射
 */
public class Context {

 private Map<Variable, Boolean> map = new HashMap<Variable, Boolean>();

 public void assign(Variable var, boolean value) {
  map.put(var, new Boolean(value));
 }

 public boolean lookup(Variable var) throws IllegalArgumentException {
  Boolean value = map.get(var);
  if (value == null) {
   throw new IllegalArgumentException();
  }
  return value.booleanValue();
 }
}
 

  客戶端類

[java] 
package com.bankht.Interpreter; 
 
/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:12:17
 * 
 * @類說明 :客戶端類
 */ 
public class Client { 
 
    public static void main(String[] args) { 
        Context ctx = new Context(); 
        Variable x = new Variable("x"); 
        Variable y = new Variable("y"); 
        Constant c = new Constant(true); 
        ctx.assign(x, false); 
        ctx.assign(y, true); 
 
        Expression exp = new Or(new And(c, x), new And(y, new Not(x))); 
        System.out.println("x=" + x.interpret(ctx)); 
        System.out.println("y=" + y.interpret(ctx)); 
        System.out.println(exp.toString() + "=" + exp.interpret(ctx)); 
    } 
 

package com.bankht.Interpreter;

/**
 * @author: 特種兵—AK47
 * @創建時間:2012-7-3 下午03:12:17
 *
 * @類說明 :客戶端類
 */
public class Client {

 public static void main(String[] args) {
  Context ctx = new Context();
  Variable x = new Variable("x");
  Variable y = new Variable("y");
  Constant c = new Constant(true);
  ctx.assign(x, false);
  ctx.assign(y, true);

  Expression exp = new Or(new And(c, x), new And(y, new Not(x)));
  System.out.println("x=" + x.interpret(ctx));
  System.out.println("y=" + y.interpret(ctx));
  System.out.println(exp.toString() + "=" + exp.interpret(ctx));
 }

}

  運行結果如下:

[html] 
x=false 
y=true 
((true AND x) OR (y AND (Not x)))=true 
   作者:m13666368773
 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。