メインコンテンツまでスキップ

🧩 Interpreter パターン

✅ 設計意図

  • ドメイン固有言語(DSL)のように、条件ロジックやルールを文法として表現し、解釈・評価できる構造を定義する

✅ 適用理由

  • 複雑で頻繁に変更される条件分岐を、構文ツリーとして定義し、評価器(interpreter)に任せる
  • if 文/switch 文がネストして保守困難になっているロジックを、柔軟に分離・追加できる形にする

✅ 向いているシーン

  • ビジネスルールエンジン、フィルタ条件、検索条件式など
  • ルールが非エンジニアや設定ファイルで記述され、実行時に評価される場合

✅ コード例

// 文法インターフェース
interface Expression {
interpret(userType: string, basePrice: number): number;
}

// ターミナル式(具体的な条件と計算)
class DiscountExpression implements Expression {
constructor(private targetType: string, private rate: number) {}

interpret(userType: string, basePrice: number): number {
return userType === this.targetType ? basePrice * this.rate : basePrice;
}
}

// 非終端式(ANDやORなどにも拡張可能)
class DiscountInterpreter {
private expressions: DiscountExpression[] = [];

add(expression: DiscountExpression) {
this.expressions.push(expression);
}

interpret(userType: string, basePrice: number): number {
for (const expr of this.expressions) {
const result = expr.interpret(userType, basePrice);
if (result !== basePrice) return result;
}
return basePrice;
}
}

// 利用例
const interpreter = new DiscountInterpreter();
interpreter.add(new DiscountExpression("student", 0.8));
interpreter.add(new DiscountExpression("member", 0.9));
interpreter.add(new DiscountExpression("vip", 0.7));

console.log(interpreter.interpret("vip", 1000)); // 700
console.log(interpreter.interpret("student", 1000)); // 800
console.log(interpreter.interpret("guest", 1000)); // 1000

✅ 解説

このコードは Interpreter パターン を使用して、割引計算のルールを文法として表現し、柔軟に評価できる設計を実現している。 Interpreter パターンは、特定の文法を定義し、その文法に従った式を評価するデザインパターンであり、特に複雑なルールや条件を扱う場合に有効。

1. Interpreter パターンの概要

  • Expression: 文法の共通インターフェースを定義
    • このコードでは Expression が該当
  • TerminalExpression: 文法の末端要素を表現し、具体的な条件や計算を実装
    • このコードでは DiscountExpression が該当
  • NonTerminalExpression: 文法の非終端要素を表現し、複数の式を組み合わせて評価
    • このコードでは DiscountInterpreter が該当
  • Client: 文法を構築し、評価を実行
    • このコードでは DiscountInterpreter に式を追加し、interpret メソッドを呼び出す部分が該当

2. 主なクラスとその役割

  • Expression
    • 文法の共通インターフェース
    • interpret(userType: string, basePrice: number): number メソッドを定義
  • DiscountExpression
    • TerminalExpression(ターミナル式)
    • 特定のユーザータイプ(targetType)に対して割引率(rate)を適用するロジックを実装
  • DiscountInterpreter
    • NonTerminalExpression(非終端式)
    • 複数の DiscountExpression を保持し、順に評価
    • 最初に一致する式が見つかった場合、その結果を返す
  • クライアントコード
    • DiscountInterpreter に複数の DiscountExpression を追加し、interpret メソッドで評価を実行

3. UML クラス図

4. Interpreter パターンの利点

  • 柔軟なルール定義: 文法をオブジェクトとして表現することで、複雑なルールを簡潔に定義可能。
  • 拡張性: 新しいルールを追加する場合も、DiscountExpression を作成して DiscountInterpreter に追加するだけで対応可能。
  • 再利用性: 各式(DiscountExpression)が独立しているため、他の文脈でも再利用可能。

この設計は、複雑な条件やルールを扱う際に非常に有効であり、特に動的にルールを変更したい場合や、条件が増える可能性がある場面で有効に機能する。