インタープリターパターン

インタープリターパターン(Interpreter Pattern)は、言語の文法や式を評価する方法を提供し、振る舞い型パターンに属します。

インタープリターパターンは、言語が与えられたとき、その文法の表現を定義し、その表現を使用して言語内の文を解釈するインタープリターを定義します。

このパターンは、SQL解析、記号処理エンジンなどで使用されます。

紹介

意図

言語の文法表現を定義し、その言語内の文を解釈できるインタープリターを作成します。

主に解決する問題

  • インタープリターパターンは、特定の言語や文法の文を解釈できるインタープリターを構築するために使用されます。

使用シーン

  • 特定のタイプの問題が頻繁に発生し、それらの問題のインスタンスを簡単な言語で表現できる場合。

実装方法

  • 文法を定義する:言語の終端記号と非終端記号を明確にします。
  • 構文ツリーを構築する:言語の文に基づいて対応する構文ツリー構造を構築します。
  • 環境クラスを作成する:解釈プロセスに必要なグローバル情報を含み、通常はHashMapです。

重要なコード

  • 終端記号と非終端記号:言語の文法構造を定義します。
  • 環境クラス:解釈プロセスに必要な外部環境情報を格納します。

応用例

  • コンパイラ:インタープリターパターンはコンパイラ設計に使用でき、ソースコードをターゲットコードに解釈します。
  • 正規表現:インタープリターパターンは正規表現の解析と実行に使用できます。
  • SQL解析:インタープリターパターンはSQL文の解析と実行に使用できます。

長所

  • 拡張性が良い:新しい式の解釈方法を追加しやすい。
  • 柔軟性:必要に応じて文法を簡単に拡張または変更できます。
  • 簡単な文法を実装しやすい:単純な言語の場合、実装は比較的容易です。

短所

  1. 使用シーンが限られる:解釈に適した単純な文法にのみ適用できます。
  2. 保守が難しい:複雑な文法の場合、保守と拡張が困難になります。
  3. クラスの肥大:多くのクラスが生成される可能性があり、各文法規則が1つのクラスに対応します。
  4. 再帰呼び出し:インタープリターパターンは通常再帰呼び出しを使用するため、理解と追跡が難しい場合があります。

使用上のアドバイス

  • 言語内の文を解釈して実行する必要がある場合は、インタープリターパターンの使用を検討してください。
  • システムが複雑になりすぎないように、文法を単純に保つようにしてください。

注意事項

  • インタープリターパターンはJavaでは最初の選択肢ではないかもしれません。適用可能なシナリオに遭遇した場合は、expression4Jなどのライブラリを使用して代用することを検討できます。

構造

インタープリターパターンには、次の主要な役割が含まれます:

  • 抽象式(Abstract Expression):インタープリターの抽象インターフェースを定義し、解釈操作のメソッドを宣言します。通常は抽象クラスまたはインターフェースです。

  • 終端式(Terminal Expression):抽象式インターフェースを実装した終端式クラスで、言語内の終端記号(変数、定数など)を表し、対応する解釈操作を実装します。

  • 非終端式(Non-terminal Expression):抽象式インターフェースを実装した非終端式クラスで、言語内の非終端記号(文、式など)を表し、対応する解釈操作を実装します。

  • コンテキスト(Context):インタープリターの外部のいくつかのグローバル情報を含み、解釈プロセス中にインタープリターに提供されます。通常、変数の値の格納やインタープリターの状態の保存などに使用されます。

  • クライアント(Client):具体的なインタープリターオブジェクトを作成および構成し、解釈する必要がある式をインタープリターに渡して解釈します。

実装

インターフェースを作成しますExpressionと、それを実装したExpressionインターフェースのエンティティクラス。コンテキスト内の主要なインタープリターとして定義するTerminalExpressionクラス。他のクラスはOrExpression、AndExpression組み合わせ式を作成するために使用されます。

InterpreterPatternDemo、私たちのデモクラスはExpressionクラスを使用してルールを作成し、式の解析をデモンストレーションします。

解释器模式的 UML 图

ステップ 1

式インターフェースを作成します。

Expression.java

public interface Expression { public boolean interpret(String context); }

ステップ 2

上記のインターフェースを実装したエンティティクラスを作成します。

TerminalExpression.java

public class TerminalExpression implements Expression { private String data; public TerminalExpression(String data){ this.data = data; } @Override public boolean interpret(String context) { if(context.contains(data)){ return true; } return false; } }

OrExpression.java

public class OrExpression implements Expression { private Expression expr1 = null; private Expression expr2 = null; public OrExpression(Expression expr1, Expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } @Override public boolean interpret(String context) { return expr1.interpret(context) || expr2.interpret(context); } }

AndExpression.java

public class AndExpression implements Expression { private Expression expr1 = null; private Expression expr2 = null; public AndExpression(Expression expr1, Expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } @Override public boolean interpret(String context) { return expr1.interpret(context) && expr2.interpret(context); } }

ステップ 3

InterpreterPatternDemo使用しExpressionクラスでルールを作成し、それらを解析します。

InterpreterPatternDemo.java

public class InterpreterPatternDemo { //ルール:Robert と John は男性です public static Expression getMaleExpression(){ Expression robert = new TerminalExpression("Robert"); Expression john = new TerminalExpression("John"); return new OrExpression(robert, john); } //ルール:Julie は既婚の女性です public static Expression getMarriedWomanExpression(){ Expression julie = new TerminalExpression("Julie"); Expression married = new TerminalExpression("Married"); return new AndExpression(julie, married); } public static void main(String[] args) { Expression isMale = getMaleExpression(); Expression isMarriedWoman = getMarriedWomanExpression(); System.out.println("John is male? " + isMale.interpret("John")); System.out.println("Julie is a married women? " + isMarriedWoman.interpret("Married Julie")); } }

ステップ 4

プログラムを実行し、結果を出力します:

John is male? true
Julie is a married women? true
その他の拡張