Yan Hon 博士の著書『JAVA and Patterns』は、Interpreter パターンの説明で始まります。
インタプリタ パターンはクラスの動作パターンです。言語が与えられると、インタプリタ パターンはその文法の表現を定義し、インタプリタを提供します。クライアントは、このインタプリタを使用して、この言語の文を解釈できます。
インタプリタモードの構造
インタプリタモードの構造を説明するために、スケマティックシステムを例に挙げてみましょう。システム構成図は以下のとおりです。
パターンに関係する役割は次のとおりです。
(1) 抽象式 (Expression) ロール: すべての具体的な式ロールが実装する必要がある抽象インターフェイスを宣言します。このインターフェイスは主に、解釈操作と呼ばれる、interprete() メソッドです。
(2) 終端式の役割: 抽象式の役割に必要なインターフェース、主に interprete() メソッドを実装します。文法内の各終端記号には、それに対応する特定の終端式があります。たとえば、単純な式 R=R1+R2 があります。ここで、R1 と R2 は終端記号であり、R1 と R2 を解析する対応するインタプリタは終端式です。
(3) 非終端式の役割: 文法の各ルールには特定の非終端式が必要です。非終端式は通常、R=R1+R2 などの文法内の演算子または他のキーワードです。「+」は非終端記号です。 、「+」を解析するインタプリタは非終端記号式です。
(4) コンテキストの役割: この役割のタスクは通常、文法内の各終端記号に対応する特定の値を格納することです。たとえば、R=R1+R2 の場合、R1 には 100 の値を割り当て、R1 には 100 の値を割り当てます。 200からR2。多くの場合、この情報は環境ロールに保存する必要があります。Map を環境ロールとして使用するだけで十分です。
インタプリタ モードの実装を説明するために、最も単純な文法と、それに対応するインタプリタ モードの実装を示します。これは、Java 言語でのブール式の操作と評価をシミュレートするものです。
この言語の終端記号はブール変数、つまり定数 true と false です。非終端式には、演算子 and、or、not などのブール式が含まれます。この簡単な文法は次のとおりです。
次のようにコードをコピーします。
式 ::= 変数 | そうでない |
And ::= 式 'AND' 式
OR ::= 式 'OR' 式
Not ::= 'NOT' 式
変数 ::= 任意の識別子
定数 ::= 'true' |
インタプリタモードの構成図は以下のとおりです。
ソースコード
抽象表現の役割
次のようにコードをコピーします。
パブリック抽象クラス式 {
/**
* 環境に応じて、このメソッドは任意の式を解釈します
*/
public abstract boolean replace(Context ctx);
/**
* 2 つの式が構造的に同じかどうかを確認します
*/
public abstract boolean equals(Object obj);
/**
* 式のハッシュ コードを返します
*/
public abstract int hashCode();
/**
* 式を文字列に変換します
*/
パブリック抽象文字列 toString();
}
Constant オブジェクトはブール定数を表します
次のようにコードをコピーします。
public class Constant extends Expression{
プライベートブール値。
public Constant(ブール値){
this.value = 値;
}
@オーバーライド
public booleanquals(Object obj) {
if(obj != null && obj インスタンスオブ定数){
return this.value == ((定数)obj).value;
}
false を返します。
}
@オーバーライド
public int hashCode() {
this.toString().hashCode() を返します。
}
@オーバーライド
public boolean replace(Context ctx) {
戻り値;
}
@オーバーライド
public String toString() {
新しい Boolean(value).toString() を返します。
}
}
Variable オブジェクトは名前付き変数を表します。コードは次のとおりです。
public class 変数 extends Expression {
プライベート文字列名。
public 変数(文字列名){
this.name = 名前;
}
@オーバーライド
public booleanquals(Object obj) {
if(obj != null && obj 変数のインスタンス)
{
this.name.equals( を返す
((変数)obj).name);
}
false を返します。
}
@オーバーライド
public int hashCode() {
this.toString().hashCode() を返します。
}
@オーバーライド
public String toString() {
名前を返します。
}
@オーバーライド
public boolean replace(Context ctx) {
ctx.lookup(this)を返します;
}
}
And クラスは論理「AND」演算を表し、2 つのブール式から論理「AND」演算を通じて新しいブール式を得る演算を表します。
次のようにコードをコピーします。
public class And extends Expression {
プライベート式 left,right;
public And(左の式, 右の式){
this.left = 左;
this.right = 右;
}
@オーバーライド
public booleanquals(Object obj) {
if(obj != null && obj インスタンスオブ And)
{
return left.equals(((And)obj).left) &&
right.equals(((And)obj).right);
}
false を返します。
}
@オーバーライド
public int hashCode() {
this.toString().hashCode() を返します。
}
@オーバーライド
public boolean replace(Context ctx) {
return left.interpret(ctx) && right.interpret(ctx);
}
@オーバーライド
public String toString() {
return "(" + left.toString() + " AND " + right.toString() + ")";
}
}
Or クラスは論理「OR」演算を表し、2 つのブール式から論理「OR」演算を通じて新しいブール式を得る演算を表します。
次のようにコードをコピーします。
public class Or extends Expression {
プライベート式 left,right;
public Or(左の式, 右の式){
this.left = 左;
this.right = 右;
}
@オーバーライド
public booleanquals(Object obj) {
if(obj != null && obj インスタンス または)
{
return this.left.equals(((Or)obj).left) && this.right.equals(((Or)obj).right);
}
false を返します。
}
@オーバーライド
public int hashCode() {
this.toString().hashCode() を返します。
}
@オーバーライド
public boolean replace(Context ctx) {
戻り left.interpret(ctx) || right.interpret(ctx);
}
@オーバーライド
public String toString() {
return "(" + left.toString() + " OR " + right.toString() + ")";
}
}
Not クラスは論理「not」演算を表します。これは、論理「not」演算を通じてブール式から新しいブール式を与える演算を表します。次のようにコードをコピーします。
public class 式を拡張しません {
プライベート式 exp;
public Not(式exp){
this.exp = exp;
}
@オーバーライド
public booleanquals(Object obj) {
if(obj != null && obj インスタンスオブ Not)
{
return exp.equals(
((非)obj).exp);
}
false を返します。
}
@オーバーライド
public int hashCode() {
this.toString().hashCode() を返します。
}
@オーバーライド
public boolean replace(Context ctx) {
リターン!exp.interpret(ctx);
}
@オーバーライド
public String toString() {
return "(Not " + exp.toString() + ")";
}
}
Context クラスは、変数からブール値へのマッピングを定義します。
次のようにコードをコピーします。
パブリック クラス コンテキスト {
private Map<Variable,Boolean> map = new HashMap<Variable,Boolean>();
public void assign(変数 var , ブール値){
map.put(var, new Boolean(value));
}
public boolean lookup(Variable var) は IllegalArgumentException{ をスローします
ブール値 = map.get(var);
if(値 == null){
新しい IllegalArgumentException() をスローします。
}
戻り値.booleanValue();
}
}
クライアントクラス
次のようにコードをコピーします。
パブリック クラス クライアント {
public static void main(String[] args) {
コンテキスト ctx = 新しいコンテキスト();
変数 x = 新しい変数("x");
変数 y = 新しい変数("y");
定数 c = 新しい定数(true);
ctx.assign(x, false);
ctx.assign(y, true);
式 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));
}
}
実行結果は次のとおりです。