このページでは、GoF(Gang of Four)が提唱した23のデザインパターンの一つである「Interpreterパターン」について解説します。
Interpreterパターンは、文法規則に基づいて文を解釈するためのパターンであり、式や文の評価を自動化する場面でよく使用されます。
具体的な使用方法やJavaでの実装例も含め、詳細に説明しますので、ぜひ参考にしてください
Interpreterパターンとは
ここでは、Interpreterパターンの概要と、その役割について説明します。
Interpreterパターンは、言語の文法を解析し、構文ツリーに基づいて文や式を評価するためのパターンです。
プログラミング言語の文法規則や、テキスト解析、SQLクエリの解釈などで使用されることが多いパターンです。
このパターンでは、与えられた文法に従った「文」を解釈し、それを適切なアクションに変換することが目的です。
特定のドメイン言語(DSL: Domain-Specific Language)を解釈する必要がある場合に有効な手法です。
Interpreterパターンのメリットとデメリット
Interpreterパターンを使用することで、文法を定義しやすくなり、解析や評価が明確になります。
しかし、複雑な文法や大規模な文を処理する際には、設計が煩雑になることがあります。
Interpreterパターンの使い方
ここでは、実際にInterpreterパターンをどのように活用するかについて解説します。
Interpreterパターンは、文法規則をクラス階層で表現し、個々のルールを組み合わせて文を解釈します。
たとえば、数式や条件式を評価するために使用される場合が多く、各文法のルールに対応するクラスを作成し、それらを組み合わせて複雑な式を解釈します。
この手法により、文法の追加や変更がしやすくなり、柔軟に対応できるようになります。
適用例
Interpreterパターンは、主に以下のような場面で活用されます。
Interpreterパターン実装サンプル
次に、Javaでの簡単なInterpreterパターンの実装例を紹介します。
この例では、簡単な四則演算を解釈するためのインタプリタを作成します
// 抽象的な式を表すインターフェース
interface Expression {
int interpret();
}
// 数値を表すクラス
class Number implements Expression {
private int number;
public Number(int number) {
this.number = number;
}
@Override
public int interpret() {
return this.number;
}
}
// 足し算を表すクラス
class Add implements Expression {
private Expression leftExpression;
private Expression rightExpression;
public Add(Expression left, Expression right) {
this.leftExpression = left;
this.rightExpression = right;
}
@Override
public int interpret() {
return leftExpression.interpret() + rightExpression.interpret();
}
}
// 引き算を表すクラス
class Subtract implements Expression {
private Expression leftExpression;
private Expression rightExpression;
public Subtract(Expression left, Expression right) {
this.leftExpression = left;
this.rightExpression = right;
}
@Override
public int interpret() {
return leftExpression.interpret() - rightExpression.interpret();
}
}
// クライアントコード
public class InterpreterPatternExample {
public static void main(String[] args) {
// "5 + 3 - 2" を解釈する
Expression expression = new Subtract(
new Add(new Number(5), new Number(3)),
new Number(2)
);
System.out.println("結果: " + expression.interpret()); // 結果: 6
}
}
この実装では、Number
クラスが数値を表し、Add
クラスが足し算を、Subtract
クラスが引き算を表しています。
クライアントコードでは、5 + 3 - 2
という式を解釈し、結果を計算しています
C++での実装例
次に、C++での簡単なInterpreterパターンの実装例を紹介します。
#include <iostream>
#include <memory>
// 抽象的な式を表すインターフェース
class Expression {
public:
virtual int interpret() = 0;
virtual ~Expression() = default;
};
// 数値を表すクラス
class Number : public Expression {
private:
int number;
public:
Number(int number) : number(number) {}
int interpret() override {
return number;
}
};
// 足し算を表すクラス
class Add : public Expression {
private:
std::unique_ptr<Expression> leftExpression;
std::unique_ptr<Expression> rightExpression;
public:
Add(std::unique_ptr<Expression> left, std::unique_ptr<Expression> right)
: leftExpression(std::move(left)), rightExpression(std::move(right)) {}
int interpret() override {
return leftExpression->interpret() + rightExpression->interpret();
}
};
// 引き算を表すクラス
class Subtract : public Expression {
private:
std::unique_ptr<Expression> leftExpression;
std::unique_ptr<Expression> rightExpression;
public:
Subtract(std::unique_ptr<Expression> left, std::unique_ptr<Expression> right)
: leftExpression(std::move(left)), rightExpression(std::move(right)) {}
int interpret() override {
return leftExpression->interpret() - rightExpression->interpret();
}
};
// クライアントコード
int main() {
// "5 + 3 - 2" を解釈する
std::unique_ptr<Expression> expression = std::make_unique<Subtract>(
std::make_unique<Add>(std::make_unique<Number>(5), std::make_unique<Number>(3)),
std::make_unique<Number>(2)
);
std::cout << "結果: " << expression->interpret() << std::endl; // 結果: 6
return 0;
}
C#での実装例
次に、C#での簡単なInterpreterパターンの実装例を紹介します。
using System;
// 抽象的な式を表すインターフェース
public interface Expression
{
int Interpret();
}
// 数値を表すクラス
public class Number : Expression
{
private int _number;
public Number(int number)
{
_number = number;
}
public int Interpret()
{
return _number;
}
}
// 足し算を表すクラス
public class Add : Expression
{
private Expression _leftExpression;
private Expression _rightExpression;
public Add(Expression left, Expression right)
{
_leftExpression = left;
_rightExpression = right;
}
public int Interpret()
{
return _leftExpression.Interpret() + _rightExpression.Interpret();
}
}
// 引き算を表すクラス
public class Subtract : Expression
{
private Expression _leftExpression;
private Expression _rightExpression;
public Subtract(Expression left, Expression right)
{
_leftExpression = left;
_rightExpression = right;
}
public int Interpret()
{
return _leftExpression.Interpret() - _rightExpression.Interpret();
}
}
// クライアントコード
public class InterpreterPatternExample
{
public static void Main(string[] args)
{
// "5 + 3 - 2" を解釈する
Expression expression = new Subtract(
new Add(new Number(5), new Number(3)),
new Number(2)
);
Console.WriteLine("結果: " + expression.Interpret()); // 結果: 6
}
}
まとめ
この記事では、GoFデザインパターンの一つであるInterpreterパターンについて解説しました。
Interpreterパターンは、特定の文法規則に基づいて文や式を解釈するためのパターンであり、複雑な解析を簡素化するために使用されます。
また、Java、C++、C#による実装例を示し、どのようにこのパターンを活用できるかについても説明しました。
他のプログラミング言語でもこのパターンを応用できるため、様々なシステムに適用可能です。
これを機に、Interpreterパターンの理解を深め、実際の開発に役立ててください。