Design Pattern / Behavioral

[デザインパターン] Interpreter パターン

小さなドメイン言語のルールを文法オブジェクトを通じて解釈し、結果を計算するパターン。

  • Design Pattern
  • Behavioral
目次

パターンの一行要約

小さなドメイン言語のルールを文法オブジェクトを通じて解釈し、結果を計算するパターン。

Unityでの典型的な使用例

  • クエスト条件 DSL を構築する場合。
  • 会話の分岐条件をデータ駆動にしたい場合。

構成要素(役割)

  • Expression
  • Terminal
  • Nonterminal
  • Context

Unityサンプル(C#)

以下のコードは、上記のシナリオを基にした簡略化された Unity の例です。

public interface IConditionExpression
{
    bool Evaluate(PlayerContext context);
}

public sealed class LevelAtLeastExpression : IConditionExpression
{
    private readonly int requiredLevel;

    public LevelAtLeastExpression(int requiredLevel)
    {
        this.requiredLevel = requiredLevel;
    }

    public bool Evaluate(PlayerContext context)
    {
        return context.PlayerLevel >= requiredLevel;
    }
}

public sealed class AndExpression : IConditionExpression
{
    private readonly IConditionExpression leftExpression;
    private readonly IConditionExpression rightExpression;

    public AndExpression(IConditionExpression leftExpression, IConditionExpression rightExpression)
    {
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }

    public bool Evaluate(PlayerContext context)
    {
        return leftExpression.Evaluate(context) && rightExpression.Evaluate(context);
    }
}

利点

  • 振る舞いが小さな単位に分離されるため、変更の影響範囲を抑えられます。
  • ルールの追加や差し替えが比較的安全に行えます。

注意点

  • オブジェクト数や間接呼び出しが増えると、フローを追いにくくなります。
  • 順序に関するバグはテストで確実に固めておくべきです。

相互作用図

文法ルールを式ツリーとして解釈し、結果を計算するフローを示します。

flowchart LR

  input["Rule String"]
  lexer["Tokenizer"]
  parser["Parser"]
  ast["Expression Tree"]
  interpreter["Interpret(context)"]
  result["bool / score"]

  input --> lexer
  lexer --> parser
  parser --> ast
  ast -->|recursive visit| interpreter
  interpreter --> result

コメント