Yan Hong 박사의 저서 "JAVA and Patterns"는 인터프리터 패턴에 대한 설명으로 시작됩니다.
인터프리터 패턴은 클래스의 동작 패턴입니다. 언어가 주어지면 인터프리터 패턴은 문법 표현을 정의하고 인터프리터를 제공합니다. 고객은 이 통역사를 사용하여 이 언어로 된 문장을 해석할 수 있습니다.
통역사 모드의 구조
통역사 모드의 구조를 논의하기 위해 개략적인 시스템을 예로 들어보겠습니다. 시스템 구조 다이어그램은 다음과 같습니다.
패턴에 관련된 역할은 다음과 같습니다.
(1) 추상 표현(Expression) 역할: 모든 구체적인 표현 역할이 구현해야 하는 추상 인터페이스를 선언합니다. 이 인터페이스는 주로 해석 작업이라고 하는 해석() 메서드입니다.
(2) 터미널 표현 역할: 추상 표현 역할에 필요한 인터페이스를 구현합니다. 주로 Interpret() 메서드를 사용하여 문법의 각 터미널 기호에 해당하는 특정 터미널 표현이 있습니다. 예를 들어 R1과 R2가 터미널 기호이고 R1과 R2를 구문 분석하는 해당 인터프리터가 터미널 표현식인 간단한 공식 R=R1+R2가 있습니다.
(3) 비단말 표현 역할: 문법의 각 규칙에는 특정 비단말 표현이 필요합니다. 비단말 표현은 일반적으로 수식과 같은 문법의 연산자 또는 기타 키워드입니다. , "+"를 구문 분석하는 인터프리터는 비종단 기호 표현입니다.
(4) 컨텍스트 역할: 이 역할의 임무는 일반적으로 각 터미널 기호에 해당하는 특정 값을 문법에 저장하는 것입니다. 예를 들어 R=R1+R2, R1에 100의 값을 할당합니다. 200에서 R2. 이 정보는 환경 역할에 저장되어야 합니다. 대부분의 경우 Map을 사용하여 환경 역할을 수행하는 것으로 충분합니다.
인터프리터 모드의 구현을 설명하기 위해 여기에 가장 간단한 문법과 해당 구현인 인터프리터 모드가 있습니다. 이는 Java 언어에서 부울 표현식의 연산 및 평가를 시뮬레이션하는 것입니다.
이 언어의 터미널 기호는 부울 변수, 즉 상수 true 및 false입니다. 비터미널 표현식에는 연산자 and, or 및 not과 같은 부울 표현식이 포함됩니다. 이 간단한 문법은 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다.
표현식 ::= 상수 |
And ::= 표현식 'AND' 표현식
Or ::= 표현식 'OR' 표현식
Not ::= 'NOT' 표현식
변수 ::= 모든 식별자
상수 ::= '참' |
통역사 모드의 구조 다이어그램은 다음과 같습니다.
소스 코드
추상 표현 역할
다음과 같이 코드 코드를 복사합니다.
공개 추상 클래스 표현식 {
/**
* 환경에 따라 이 방법은 주어진 표현을 해석합니다.
*/
공개 추상 부울 해석(Context ctx);
/**
* 두 표현식이 구조적으로 동일한지 확인
*/
공개 추상 부울 같음(Object obj);
/**
* 표현식의 해시 코드를 반환합니다.
*/
공개 추상 int hashCode();
/**
* 표현식을 문자열로 변환
*/
공개 추상 문자열 toString();
}
Constant 객체는 부울 상수를 나타냅니다.
다음과 같이 코드 코드를 복사합니다.
공개 클래스 상수는 표현식을 확장합니다.
개인 부울 값;
공개 상수(부울 값){
this.value = 값;
}
@보수
공개 부울 같음(객체 obj) {
if(obj != null && obj 인스턴스of 상수){
return this.value == ((Constant)obj).value;
}
거짓을 반환;
}
@보수
공개 int hashCode() {
return this.toString().hashCode();
}
@보수
공개 부울 해석(컨텍스트 ctx) {
반환값;
}
@보수
공개 문자열 toString() {
return new Boolean(value).toString();
}
}
Variable 객체는 명명된 변수를 나타냅니다. 코드는 다음과 같습니다.
공개 클래스 변수는 표현식을 확장합니다.
개인 문자열 이름;
공용변수(문자열명){
this.name = 이름;
}
@보수
공개 부울 같음(객체 obj) {
if(obj != null && obj 인스턴스변수)
{
this.name.equals(를 반환합니다.
((변수)obj).이름);
}
거짓을 반환;
}
@보수
공개 int hashCode() {
return this.toString().hashCode();
}
@보수
공개 문자열 toString() {
이름 반환;
}
@보수
공개 부울 해석(컨텍스트 ctx) {
ctx.lookup(this)를 반환합니다.
}
}
And 클래스는 논리 "AND" 연산을 통해 두 개의 부울 표현식에서 새로운 부울 표현식을 제공하는 연산을 나타내는 논리적 "AND" 연산을 나타냅니다.
다음과 같이 코드 코드를 복사합니다.
공개 클래스 및 표현식 { 확장
개인 표현식 왼쪽, 오른쪽;
public And(왼쪽 표현식, 오른쪽 표현식){
this.left = 왼쪽;
this.right = 오른쪽;
}
@보수
공개 부울 같음(객체 obj) {
if(obj != null && obj 인스턴스of And)
{
return left.equals(((And)obj).left) &&
right.equals(((And)obj).right);
}
거짓을 반환;
}
@보수
공개 int hashCode() {
return this.toString().hashCode();
}
@보수
공개 부울 해석(컨텍스트 ctx) {
return left.interpret(ctx) && right.interpret(ctx);
}
@보수
공개 문자열 toString() {
return "(" + left.toString() + " AND " + right.toString() + ")";
}
}
Or 클래스는 논리적 "OR" 연산을 나타내며, 이는 논리적 "OR" 연산을 통해 두 개의 부울 표현식에서 새로운 부울 표현식을 제공하는 연산을 나타냅니다.
다음과 같이 코드 코드를 복사합니다.
공개 클래스 또는 표현식을 확장합니다.
개인 표현식 왼쪽, 오른쪽;
public Or(왼쪽 표현식, 오른쪽 표현식){
this.left = 왼쪽;
this.right = 오른쪽;
}
@보수
공개 부울 같음(객체 obj) {
if(obj != null && obj 인스턴스of Or)
{
return this.left.equals(((Or)obj).left) && this.right.equals(((Or)obj).right);
}
거짓을 반환;
}
@보수
공개 int hashCode() {
return this.toString().hashCode();
}
@보수
공개 부울 해석(컨텍스트 ctx) {
return left.interpret(ctx) || right.interpret(ctx);
}
@보수
공개 문자열 toString() {
return "(" + left.toString() + " OR " + right.toString() + ")";
}
}
Not 클래스는 논리적 "not" 연산을 통해 부울 표현식에서 새로운 부울 표현식을 제공하는 연산을 나타내는 논리적 "not" 연산을 나타냅니다.
공개 클래스 확장되지 않음 표현식 {
개인 표현 특급;
공개 Not(표현식 표현){
this.exp = 특급;
}
@보수
공개 부울 같음(객체 obj) {
if(obj != null && obj instanceof Not)
{
exp.equals(
((아님)obj).exp);
}
거짓을 반환;
}
@보수
공개 int hashCode() {
return this.toString().hashCode();
}
@보수
공개 부울 해석(컨텍스트 ctx) {
return !exp.interpret(ctx);
}
@보수
공개 문자열 toString() {
return "(Not " + exp.toString() + ")";
}
}
Context 클래스는 변수에서 부울 값으로의 매핑을 정의합니다.
다음과 같이 코드 코드를 복사합니다.
공개 클래스 컨텍스트 {
private Map<Variable,Boolean> map = new HashMap<Variable,Boolean>();
public void 할당(변수 var, 부울 값){
map.put(var, new Boolean(value));
}
공개 부울 조회(Variable var)에서 IllegalArgumentException이 발생합니다.
불리언 값 = map.get(var);
if(값 == null){
새로운 IllegalArgumentException()을 던져라;
}
return value.booleanValue();
}
}
클라이언트 클래스
다음과 같이 코드 코드를 복사합니다.
공개 클래스 클라이언트 {
공개 정적 무효 메인(String[] args) {
컨텍스트 ctx = 새로운 컨텍스트();
변수 x = new Variable("x");
변수 y = new Variable("y");
상수 c = 새로운 상수(true);
ctx.할당(x, false);
ctx.할당(y, true);
표현식 exp = new Or(new And(c,x) , new And(y,new Not(x)));
System.out.println("x=" + x.interpret(ctx));
System.out.println("y=" + y.interpret(ctx));
System.out.println(exp.toString() + "=" + exp.interpret(ctx));
}
}
실행 결과는 다음과 같습니다.