인터프리터 패턴
개요
태그가 article이거나, video이면서 captioned인 항목을 고르고 싶다고 하자. 이런 조건을 여러 곳의 중첩 if문으로 복사하는 대신, 조건과 결합 규칙을 객체로 표현할 수 있다.
인터프리터(Interpreter)는 언어의 식을 객체로 만들고 각 식이 자신의 의미를 계산하게 한다. 더 나뉘지 않는 태그 조건과, 식 두 개를 묶는 AND·OR가 이 작은 규칙 언어의 구성 요소다.
UML
HasTag, And, Or는 IExpr를 구현한다. And와 Or는 다른 IExpr 두 개를 참조하고, 그 결과를 결합해 자기 결과를 만든다.
역사
GoF는 1994년 Design Patterns에서 Interpreter를 행위 패턴으로 정리했다. 문법을 표현하는 구조와 그 표현의 의미를 계산하는 동작을 함께 둔다.1
왜 사용하는가?
조건을 조합한 구조 자체를 보관하고 재사용할 수 있다. 호출부는 식 전체에 Eval()을 요청하며, 하위 식을 계산하는 순서는 각 식이 정한다.
예제는 문자열을 읽어 문법 구조로 바꾸는 파서를 포함하지 않는다. 문법이 커지거나 입력이 외부에서 온다면 기존 파서 도구와 식 크기·깊이 제한도 함께 검토한다.
예제
태그 하나를 검사하는 가장 작은 식을 만든다.
using System;
using System.Collections.Generic;
using System.Linq;
IExpr rule = new HasTag("article");
Console.WriteLine(rule.Eval(new HashSet<string> { "article" }));
interface IExpr { bool Eval(IReadOnlySet<string> tags); }
sealed record HasTag(string Tag) : IExpr
{
public bool Eval(IReadOnlySet<string> tags) => tags.Contains(Tag);
}
sealed record And(IExpr Left, IExpr Right) : IExpr
{
public bool Eval(IReadOnlySet<string> tags) => Left.Eval(tags) && Right.Eval(tags);
}
sealed record Or(IExpr Left, IExpr Right) : IExpr
{
public bool Eval(IReadOnlySet<string> tags) => Left.Eval(tags) || Right.Eval(tags);
}
TrueHasTag가 이 언어의 말단 식이다. 여기서는 문자열을 코드로 실행하지 않고 태그 집합에 해당 값이 있는지만 본다.
범위 넓힌 예제
article 또는 video AND captioned 규칙을 객체 트리로 만들고 세 입력에 적용한다.
using System;
using System.Collections.Generic;
using System.Linq;
IExpr rule = new Or(new HasTag("article"), new And(new HasTag("video"), new HasTag("captioned")));
foreach (var tags in new[]
{
new HashSet<string> { "article" },
new HashSet<string> { "video" },
new HashSet<string> { "video", "captioned" }
}) Console.WriteLine(rule.Eval(tags));
interface IExpr { bool Eval(IReadOnlySet<string> tags); }
sealed record HasTag(string Tag) : IExpr
{
public bool Eval(IReadOnlySet<string> tags) => tags.Contains(Tag);
}
sealed record And(IExpr Left, IExpr Right) : IExpr
{
public bool Eval(IReadOnlySet<string> tags) => Left.Eval(tags) && Right.Eval(tags);
}
sealed record Or(IExpr Left, IExpr Right) : IExpr
{
public bool Eval(IReadOnlySet<string> tags) => Left.Eval(tags) || Right.Eval(tags);
}
True
False
TrueAnd와 Or가 자식 식의 결과를 결합한다. video만 있는 두 번째 입력은 거절하고 captioned까지 있는 세 번째 입력은 통과한다. 이 규칙은 콘텐츠 분류 예제이며 권한 판정 시스템은 아니다.
같이 보기
각 예제는 독립된 .NET 10 콘솔 프로그램이다.