目次へ

23.Interpreter パターン

  • 2012/04/26 一部修正しました

23.1 Interpreter パターンとは

第23章では Interpreter パターンを学びます。Interpreter とは、英語で「解釈者・説明者」を意味する単語です。 何らかのフォーマットで書かれたファイルの中身を、解析した結果に則って何らかの処理を行いたい場合があります。 Interpreter パターンとは、このような「解析した結果」得られた手順に則った処理を実現するために最適なパターンです。

    1 + 2 × ( 4 + 2 ) 
    

という計算式を処理する場合を考えて見ましょう。まずは、処理を解析すると、以下のような構文木が得られます。

クラス図

このような構文木に則った処理を実現するには、Interpreter パターンが利用できます。

23.2 サンプルケース

サンプルケースでは、「あきちゃんラーメンの作り方」を考えて見ましょう。
あきちゃんラーメンは、今日本でもっとも売れている即席めんです。この即席めんの作り方は、

  1. カップめんに「粉末スープ」を入れる
  2. お湯を注ぐ
  3. 3分待つ
  4. 液体スープを入れる

このようにとっても簡単にできてしまいます。これを構文木にして見みたのが以下の図です。

クラス図

この構文木から「処理」と「処理対象」を抜き出してみましょう。
「処理」に分類されるものは、「足す」「3分待つ」の2つです。一方「処理対象」に分類されるものは、 「粉末スープ」「麺」「お湯」「液体スープ」だけでなく「粉末スープと麺を足したもの」 「粉末スープと麺を足したものにお湯を足したもの」「粉末スープと麺を足したものにお湯を足したものを3分置いたもの」 なども、処理対象と考えられます。
このように、「処理対象」には「処理結果」も含まれるため、この2つを同一視するために、 Interpreter パターンは Composit パターンと同じ構造をとります。
まずは、ソースコードを見てみましょう。

/**
 * 処理対象を表すインタフェース
 */
public interface Operand {
    /**
     * 処理対象を表す文字列を返すメソッドです。
     * @return operandString
     */
    public String getOperandString();

}

「処理対象」「処理結果」を表すクラスは、このインタフェースを実装します。

/**
 * 処理対象を表すクラス
 */
public class Ingredient implements Operand {
    /**
     * この処理対象を表す文字列
     */
    private String operandString = null;

    /**
     * 処理対象を表す文字列を引数に取るコンストラクタ
     * @param operandString
     */
    public Ingredient(String operandString) {
        this.operandString = operandString;
    }

    /**
     * 処理対象を表す文字列を返すメソッド
     * @return operandString
     */
    public String getOperandString() {
        return this.operandString;
    }
}
/**
 * 処理結果を表すクラス
 */
public class Expression implements Operand {
    /**
     * operator
     */
    private Operator operator = null;

    /**
     * 処理内容を表す operator を引数に取るコンストラクタ
     * @param operator
     */
    public Expression(Operator operator) {
        this.operator = operator;
    }

    /**
     * 処理の結果得られる Operand の文字列表現を返すメソッド
     * @return operandString
     */
    public String getOperandString() {
        return operator.execute().getOperandString();
    }
}

処理を表すインタフェースは、以下のようになります。

/**
 * 処理を表すインタフェース
 */
public interface Operator {
    /**
     * 実行結果の operand を返すメソッド
     * @return operand
     */
    public Operand execute();
}
/**
 * 足し合わせる処理を表すクラス
 */
public class Plus implements Operator {
    private Operand operand1 = null;
    private Operand operand2 = null;

    /**
     * 足される2つの operand を引数に取るコンストラクタ
     * @param operand1
     * @param operand2
     */
    public Plus(Operand operand1, Operand operand2) {
        this.operand1 = operand1;
        this.operand2 = operand2;
    }

    /**
     * 処理を実行するメソッド
     * @return string
     */
    public Operand execute() {
        return new Ingredient(operand1.getOperandString() + "と"
                + operand2.getOperandString() + "を足したもの");
    }
}
/**
 * 「待つ」という処理を表すクラス
 */
public class Wait implements Operator {

    private int minutes = -1;
    private Operand operand = null;

    /**
     * 足される2つの operand を引数に取るコンストラクタ
     * @param minutes
     * @param operand
     */
    public Wait(int minutes, Operand operand) {
        this.minutes = minutes;
        this.operand = operand;
    }

    /**
     * 処理を実行するメソッド
     * @return string
     */
    public Operand execute() {
        return new Ingredient(operand.getOperandString() + "を" + minutes
                + "分置いたもの");
    }
}

以上をクラス図で表すと以下のようになります。

クラス図

Interpreter パターンでは、ひとつの文法規則をひとつのクラスで表現します。
サンプルケースでは、「足す」「待つ」といった処理をひとつのクラスで表現しており、 構文の解析結果に合わせて、処理を実行していくことを可能にしています。

23.3 Interpreter パターンまとめ

Interpreter パターンの一般的なクラス図は、以下のようになります。

クラス図
[引用] 『Java言語で学ぶ デザインパターン入門』(結城浩 ソフトバンクパブリッシング株式会社出版 2001年)

↑このページの先頭へ

こちらもチェック!

PR
  • XMLDB.jp