Interpreter pattern is used to represent common operations. If we want to implement any custom rule/calculation/operations/language then we can use the interpreter pattern.
This article demonstrates Interpreter pattern implementations in Golang. Check the following examples.
Implementation
Here are the steps for Interpreter pattern implementation in Golang-
- Create an interface for the operations.
- Create a struct for the terminal operation. This is the main operation struct. Define the main operation/calculation in the method, which is defined for execution. This struct should implement the interface.
- Define struct for each operation. Declare fields in the struct to store the operands, of type of the operation interface. In the execution method perform the operation.
Examples
Here are a few examples of Interpreter pattern implementation in Go-
Example #1: Logical Operation
Let’s take the example of operations like AND, OR, XOR, etc. We are checking if a string contains any specific string(sub-string), and we will evaluate the operations AND, OR, XOR etc. based on that.
Operation Interface
- Create file “operation.go”.
- Define interface “Operation”.
- Declare method “Execute”.
// operation.go
package main
type Operation interface {
Execute(opContext string) bool
}
Terminal Operation Struct
- Create file “terminal_operation.go”.
- Define struct “TerminalOpertion”.
- Declare field “data” of type of string.
- Create method “NewTerminalOperation”, which will generate a new struct and set the data value.
- Implement interface “Operation” for the struct. Define method “Execute” as part of the interface implementation.
- In the “Execute” method check if the passed string contains the “data” filled value.
// terminal_operation.go
package main
import "strings"
type TerminalOperation struct {
data string
}
func NewTerminalOperation(data string) (terminalOperation *TerminalOperation) {
terminalOperation = &TerminalOperation{}
terminalOperation.data = data
return
}
func (terminalOperation *TerminalOperation) Execute(opContext string) bool {
return strings.Contains(opContext, terminalOperation.data)
}
AND Operation Struct
- Create file “and_operation.go”.
- Define struct “AndOperation”.
- Declare fields “op1” and “op2” of the type of “Opertion”.
- Create method “NewAndOperation”, which will generate a new struct and set the field values.
- Implement interface “Operation” for the struct.
- In the “Execute” method call the “Execute” methods from the “op1” and “op2” and the perform “AND” (&&) operation on those two operands.
// and_operation.go
package main
type AndOperation struct {
op1 Operation
op2 Operation
}
func NewAndOperation(op1 Operation, op2 Operation) (andOperation *AndOperation) {
andOperation = &AndOperation{}
andOperation.op1 = op1
andOperation.op2 = op2
return
}
func (andOperation *AndOperation) Execute(opContext string) bool {
return andOperation.op1.Execute(opContext) && andOperation.op2.Execute(opContext)
}
OR Operation Struct
- Create file “or_operation.go”.
- Define struct “OrOperation”.
- Declare fields “op1” and “op2” of the type of “Operation”.
- Create method “NewOrOperation”, to generate a new struct and set the field values.
- Implement interface “Operation” for the struct. In the “Execute” method call the “Execute” methods from the “op1” and “op2” and the perform “OR” (||) operation on those two operands.
// or_operation.go
package main
type OrOperation struct {
op1 Operation
op2 Operation
}
func NewOrOperation(op1 Operation, op2 Operation) (orOperation *OrOperation) {
orOperation = &OrOperation{}
orOperation.op1 = op1
orOperation.op2 = op2
return
}
func (orOperation *OrOperation) Execute(opContext string) bool {
return orOperation.op1.Execute(opContext) || orOperation.op2.Execute(opContext)
}
XOR Operation Struct
- Create file “xor_operation.go”.
- Define struct “XorOperation”.
- Declare fields “op1” and “op2” of the type of “Operation”.
- Create method “NewXorOperation”.
- Implement interface “Operation” for the struct. In the “Execute” method call the “Execute” methods from the “op1” and “op2” and the perform “XOR” operation on those two operands.
// xor_operation.go
package main
type XorOperation struct {
op1 Operation
op2 Operation
}
func NewXorOperation(op1 Operation, op2 Operation) (xorOperation *XorOperation) {
xorOperation = &XorOperation{}
xorOperation.op1 = op1
xorOperation.op2 = op2
return
}
func (xorOperation *XorOperation) Execute(opContext string) bool {
return xorOperation.op1.Execute(opContext) != xorOperation.op2.Execute(opContext)
}
Demo
For using the implementation, we can create 2 “TerminalOperation” and then define AND/OR/XOR operations.
Then we can call the “Execute” method and perform the operations.
// main.go
package main
import "fmt"
func main() {
op1 := NewTerminalOperation("Big")
op2 := NewTerminalOperation("Box")
andChecker := NewAndOperation(op1, op2)
orChecker := NewOrOperation(op1, op2)
xorChecker := NewXorOperation(op1, op2)
checkStr1 := "Big Box Code"
checkStr2 := "Only Big Code"
checkStr3 := "Only Box Code"
checkStr4 := "No Code"
andResult1 := andChecker.Execute(checkStr1)
andResult2 := andChecker.Execute(checkStr2)
andResult3 := andChecker.Execute(checkStr3)
andResult4 := andChecker.Execute(checkStr4)
fmt.Printf("Data: %v; AND Result: %vn", checkStr1, andResult1)
fmt.Printf("Data: %v; AND Result: %vn", checkStr2, andResult2)
fmt.Printf("Data: %v; AND Result: %vn", checkStr3, andResult3)
fmt.Printf("Data: %v; AND Result: %vn", checkStr4, andResult4)
orResult1 := orChecker.Execute(checkStr1)
orResult2 := orChecker.Execute(checkStr2)
orResult3 := orChecker.Execute(checkStr3)
orResult4 := orChecker.Execute(checkStr4)
fmt.Printf("Data: %v; OR Result: %vn", checkStr1, orResult1)
fmt.Printf("Data: %v; OR Result: %vn", checkStr2, orResult2)
fmt.Printf("Data: %v; OR Result: %vn", checkStr3, orResult3)
fmt.Printf("Data: %v; OR Result: %vn", checkStr4, orResult4)
xorResult1 := xorChecker.Execute(checkStr1)
xorResult2 := xorChecker.Execute(checkStr2)
xorResult3 := xorChecker.Execute(checkStr3)
xorResult4 := xorChecker.Execute(checkStr4)
fmt.Printf("Data: %v; XOR Result: %vn", checkStr1, xorResult1)
fmt.Printf("Data: %v; XOR Result: %vn", checkStr2, xorResult2)
fmt.Printf("Data: %v; XOR Result: %vn", checkStr3, xorResult3)
fmt.Printf("Data: %v; XOR Result: %vn", checkStr4, xorResult4)
}
Output
Output will be as below.
Data: Big Box Code; AND Result: true
Data: Only Big Code; AND Result: false
Data: Only Box Code; AND Result: false
Data: No Code; AND Result: false
Data: Big Box Code; OR Result: true
Data: Only Big Code; OR Result: true
Data: Only Box Code; OR Result: true
Data: No Code; OR Result: false
Data: Big Box Code; XOR Result: false
Data: Only Big Code; XOR Result: true
Data: Only Box Code; XOR Result: true
Data: No Code; XOR Result: false
Source Code
Use the following link to get the source code:
Example | Source Code Link |
---|---|
Example #1: Logical Operation | GitHub |
Other Code Implementations
Use the following links to check Interpreter pattern implementation in other programming languages.