Skip to content

Latest commit

 

History

History
181 lines (142 loc) · 7.84 KB

3C. Interpreter.md

File metadata and controls

181 lines (142 loc) · 7.84 KB

Interpreter

The Interpreter pattern is a behavioral design pattern that is used to define a language or grammar for a problem domain and provides a way to evaluate or interpret sentences in that language. It allows you to build an interpreter that can parse sentences in the defined language and perform actions based on the parsed expressions.

image

interface Vehicle {
    void drive();
    void stop();
    void refuel();
}

// Context
class Car implements Vehicle {
    private String plateNumber;

    public Car(String plateNumber) {
        this.plateNumber = plateNumber;
    }

    @Override
    public void drive() {
        System.out.println("The car " + plateNumber + " is driving.");
    }

    @Override
    public void stop() {
        System.out.println("The car " + plateNumber + " has stopped.");
    }

    @Override
    public void refuel() {
        System.out.println("The car " + plateNumber + " is being refueled.");
    }
}

// Context
class Truck implements Vehicle {
    private String plateNumber;

    public Truck(String plateNumber) {
        this.plateNumber = plateNumber;
    }

    @Override
    public void drive() {
        System.out.println("The truck " + plateNumber + " is driving.");
    }

    @Override
    public void stop() {
        System.out.println("The truck" + plateNumber + " has stopped.");
    }

    @Override
    public void refuel() {
        System.out.println("The truck " + plateNumber + " is being refueled.");
    }
}

// Abstract Expression Interface
interface Expression {
    void interpret(Vehicle vehicle);
}

// Terminal Expresion
class DriveExpression implements Expression {
    @Override
    public void interpret(Vehicle vehicle) {
        vehicle.drive();
    }
}

// Terminal Expresion
class StopExpression implements Expression {
    @Override
    public void interpret(Vehicle vehicle) {
        vehicle.stop();
    }
}

// Terminal Expresion
class RefuelExpression implements Expression {
    @Override
    public void interpret(Vehicle vehicle) {
        vehicle.refuel();
    }
}

// Non-Terminal Expresion
class CompositeExpression implements Expression {
    private List<Expression> expressions;

    public CompositeExpression() {
        expressions = new ArrayList<>();
    }

    public void addExpression(Expression expression) {
        expressions.add(expression);
    }

    @Override
    public void interpret(Vehicle vehicle) {
        for (Expression expression : expressions) {
            expression.interpret(vehicle);
        }
    }
}

class CommandParser {
    private final Map<String, Expression> expressions;

    public CommandParser() {
        expressions = new HashMap<>();
        expressions.put("drive", new DriveExpression());
        expressions.put("stop", new StopExpression());
        expressions.put("refuel", new RefuelExpression());
    }

    public void parse(String command, Vehicle vehicle) {
        Expression expression = expressions.get(command);
        if (expression != null) {
            expression.interpret(vehicle);
        } else {
            System.out.println("Invalid command: " + command);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle car = new Car("ABC123");
        StopExpression stop = new StopExpression();
        RefuelExpression refuel = new RefuelExpression();
        stop.interpret(car);  // Output: The car ABC123 has stopped.
        refuel.interpret(car);  // Output: The car ABC123 is being refueled.

        // Interpret commands using the parser
        CommandParser parser = new CommandParser();
        parser.parse("drive", car);  // Output: The car ABC123 is driving.
        parser.parse("stop", car);  // Output: The car ABC123 has stopped.
        parser.parse("refuel_stop", car);  // Output: Invalid command: refuel_stop
        parser.parse("park", car);  // Output: Invalid command: park

        // Create a composite expression for refueling and stopping
        CompositeExpression compositeExpression = new CompositeExpression();
        compositeExpression.addExpression(new StopExpression());
        compositeExpression.addExpression(new RefuelExpression());
        compositeExpression.interpret(car);  // Output: The car ABC123 has stopped. The car ABC123 is being refueled.
    }
}

In this example, say we want to define a simple language for specifying actions or commands related to vehicles. We might have commands like "drive", "stop", "refuel", etc. Each command can be associated with a specific action that should be performed on a vehicle.

Certainly! The Interpreter pattern is a behavioral design pattern that is used to define a language or grammar for a problem domain and provides a way to evaluate or interpret sentences in that language. It allows you to build an interpreter that can parse sentences in the defined language and perform actions based on the parsed expressions.

In the context of the Vehicle example, let's say we want to define a simple language for specifying actions or commands related to vehicles. For example, we might have commands like "drive", "stop", "refuel", etc. Each command can be associated with a specific action that should be performed on a vehicle.

We'll need the following components to implement the interpreter pattern:

  1. Abstract Expression (Expression): This interface represents the abstract syntax tree node of the language. It declares an interpret method that takes a Vehicle object and performs the specific action associated with the expression.

  2. Terminal Expression (TerminalExpression): This class implements the Expression interface and represents the terminal expressions or leaf nodes of the abstract syntax tree. In our example, we can have classes like DriveExpression, StopExpression, RefuelExpression, etc., which implement the interpret method accordingly.

  3. Non-terminal Expression (NonTerminalExpression): This class (CompositeExpression) also implements the Expression interface and represents the non-terminal expressions or composite nodes of the abstract syntax tree. It can contain multiple child expressions and implement the interpret method by performing some composite operation.

We define the Expression interface that declares the interpret method. Each concrete expression class (DriveExpression, StopExpression, RefuelExpression) implements the interpret method to perform the specific action on the Vehicle object. The CommandParser class acts as the interpreter and contains a mapping of commands to corresponding expressions. It parses the input command and invokes the interpret method on the corresponding expression. If the command is not recognized, it displays an error message.

Interpreter Design Pattern Summary

Use the Interpreter pattern when you need to interpret and evaluate expressions or grammars in your application (SQL,Regex ...)

  • It's best to design apply this pattern when you have a language or a domain-specific problem that can be represented as an Abstract Syntax Tree (AST)
  • Or when you want to create a domain-specific language (DSL) or provide a way to specify complex rules or behaviors using a simple syntax.

Use the Interpreter pattern when you want to decouple the grammar and rules from the implementation details of the expressions.

Use the Interpreter pattern when the grammar is simple and stable, but you expect frequent variations or extensions in the expressions.

NOTE

The usage of the Interpreter pattern can be extremely rare. However, it is commonly seen used in areas such as query languages, regular expressions, mathematical expressions, template engines, and rule-based systems. It allows you to define a language, grammar, or set of rules and provide a way to interpret and process them efficiently.