แบบแผนอินเทอร์พรีเตอร์

**แบบแผนตัวแปลคำสั่ง** หรือ **แบบแผนอินเทอร์พรีเตอร์** (Interpreter pattern) เป็นแบบแผนการออกแบบซอฟต์แวร์ ที่ใช้ในกรณีที่ขอบเขตของปัญหาสามารถถูกอธิบายในลักษณะที่เป็นภาษาและกฎที่แน่นอนตายตัว เราสามารถสร้างคลาสที่เป็นตัวแทนขององค์ประกอบของภาษา จัดเรียงเข้าด้วยกันเพื่ออธิบายปัญหาหนึ่ง ๆ และแปลหรือประเมินผลโดยใช้โครงสร้างที่ได้จัดเรียงไว้นั้น ตัวอย่างเช่น สูตรคณิตศาสตร์ต่าง ๆ หรือยกตัวอย่างให้เฉพาะเจาะจงเช่น สูตรเรขาคณิตสำหรับหาพื้นที่รูปสามเหลี่ยม

พื้นที่รูปสามเหลี่ยม = 1/2 * ความยาวฐาน * ความสูง

## การนำไปใช้งาน

จากการที่ปัญหาส่วนใหญ่เมื่อถูกอธิบายในแบบที่เป็นนิยามภาษาจะมีลักษณะที่เป็น recursive คือปัญหาใหญ่ ๆ จะถูกแก้ได้โดยการแบ่งแยกเป็นปัญหาย่อย ๆ และแก้ปัญหาย่อย ๆ ลงไปตามลำดับ ๆ จนในที่สุดถึงปัญหาที่ไม่จำเป็นต้องแบ่งย่อยอีก ทำให้องค์ประกอบของแบบแผนอินเทอร์พรีเตอร์มีลักษณะเดียวกับแบบแผนคอมโพสิต

องค์ประกอบของแบบแผนอินเทอร์พรีเตอร์มีดังนี้
* อินเตอร์เฟสหรือคลาสแบบแอ็บสแตรคเป็นแม่แบบที่นิยามพฤติกรรมที่แต่ละอ็อบเจกต์ของอินเทอร์พรีเตอร์ต้องมี
* คลาสที่สามารถมีองค์ประกอบอื่นของอินเทอร์พรีเตอร์ได้
* คลาสที่เป็นส่วนปลาย ไม่สามารถมีองค์ประกอบอื่นได้
* คลาสสำหรับเป็นบริบท (context) หรือองค์ประกอบที่ใช้ในการประเมินผล

[frame|center|[UML คลาสไดอะแกรมของแบบแผนอินเทอร์พรีเตอร์]]

## ตัวอย่างโปรแกรม

### ภาษาจาวา

ตัวอย่างโปรแกรมเพื่อคำนวณหาพื้นที่รูปสามเหลี่ยมโดยสูตร พื้นที่รูปสามเหลี่ยม = 1/2 * ความยาวฐาน * ความสูง

อินเตอร์เฟส `Expression` เป็นแม่แบบของส่วนประกอบต่างๆ ของคอมโพสิต นิยามเมธอด `evaluate()` เพื่อให้แต่ละองค์ประกอบประเมินผลในส่วนของตัวเองและองค์ประกอบย่อยที่อยู่ภายใต้ ในที่นี้เราใช้ `HashMap` เป็น context เพื่อส่งผ่านค่าคัวแปรไปให้คลาสชนิด `Variable` ใช้ในการประเมินผล


```java
import java.util.HashMap;

public interface Expression {
    public double evaluate(HashMap<String, Double> context) throws Exception;
}
```


คลาส `Multiplication` เปรียบเสมือนเครื่องหมายคูณ สามารถมีองค์ประกอบย่อยได้สองตัวคือตัวคูณข้างซ้ายและตัวคูณข้างขวา


```java
import java.util.HashMap;

public class Multiplication implements Expression {
    private final Expression operand1;
    private final Expression operand2;

    public Multiplication(Expression operand1, Expression operand2) {
        this.operand1 = operand1;
        this.operand2 = operand2;
    }

    public double evaluate(HashMap<String, Double> context) throws Exception {
        return operand1.evaluate(context) * operand2.evaluate(context);
    }
}
```


คลาส `Division` เปรียบเสมือนเครื่องหมายหาร สามารถมีองค์ประกอบย่อยได้สองตัวคือตัวถูกหารและตัวหาร


```java
import java.util.HashMap;

public class Division implements Expression {
    private final Expression operand1;
    private final Expression operand2;

    public Division(Expression operand1, Expression operand2) {
        this.operand1 = operand1;
        this.operand2 = operand2;
    }

    public double evaluate(HashMap<String, Double> context) throws Exception {
        return operand1.evaluate(context) / operand2.evaluate(context);
    }
}
```


คลาส `Constant` เปรียบเสมือนค่าคงที่ในสมการ ไม่มีองค์ประกอบย่อย


```java
import java.util.HashMap;

public class Constant implements Expression {
    private final double value;

    public Constant(double value) {
        this.value = value;
    }

    public double evaluate(HashMap<String, Double> context) {
        return value;
    }
}
```


คลาส `Variable` เปรียบเสมือนตัวแปรในสมการ มีหน้าที่หาค่าของตนเองจาก context ไม่มีองค์ประกอบย่อย


```java
import java.util.HashMap;

public class Variable implements Expression {
    private final String name;

    public Variable(String name) {
        this.name = name;
    }

    public double evaluate(HashMap<String, Double> context) throws Exception {
        Double value = context.get(name);
        if (value == null)
            throw new Exception("Unbound variable: " + name);

        return value;
    }
}
```


การเรียกใช้งาน


```java
HashMap<String, Double> context = new HashMap<String, Double>();
context.put("base", 10.0);
context.put("height", 5.0);

Expression two = new Constant(2);
Expression base = new Variable("base");
Expression height = new Variable("height");

Expression multi = new Multiplication(base, height);
Expression triangleArea = new Division(multi, two);

double result = triangleArea.evaluate(context);
```


## อ้างอิง
* Design Patterns: Elements of Reusable Object-Oriented Software (ISBN 0-201-63361-2) โดย Erich Gamma, Richard Helm, Ralph Johnson และ John Vlissides (Gang of four: GoF)

## แหล่งข้อมูลอื่น
* Interpreter โดย Vince Huston 

หมวดหมู่:การเขียนโปรแกรม