行为型 - 10. 解释器模式

90 阅读2分钟

解释器模式(Interpreter design pattern),它用来描述如何构建一个简单的“语言”解释器。比起命令模式,解释器模式更加小众,只在一些特定的领域会被用到,比如编译器、规则引擎、正则表达式。

1. 解释器模式的原理

解释器模式为某个语言定义它的语法(或者叫文法)表示,并定义一个解释器用来处理这个语法。

Interpreter pattern is used to defines a grammatical representation for a language and provides an interpreter to deal with this grammar.

要想了解“语言”表达的信息,就必须定义相应的语法规则。这样,书写者就可以根据语法规则来书写“句子”(专业点的叫法应该是“表达式”),阅读者根据语法规则来阅读“句子”,这样才能做到信息的正确传递。解释器模式,其实就是用来实现根据语法规则解读“句子”的解释器。

它的代码实现的核心思想,就是将语法解析的工作拆分到各个小类中,以此来避免大而全的解析类。一般的做法是,将语法规则拆分一些小的独立的单元,然后对每个单元进行解析,最终合并为对整个语法规则的解析。

2. 解释器模式的实现

type Expression interface {
   interpreter() int
}

type NumberExpression struct {
   number int
}

func NewNumberExpression(num string) *NumberExpression {
   number, _ := strconv.Atoi(num)
   return &NumberExpression{number}
}

func (n *NumberExpression) interpreter() int {
   return n.number
}

type AdditionExpression struct {
   exp1, exp2 Expression
}

func NewAdditionExpression(exp1, exp2 Expression) *AdditionExpression {
   return &AdditionExpression{exp1, exp2}
}

func (a *AdditionExpression) interpreter() int {
   return a.exp1.interpreter() + a.exp2.interpreter()
}

type SubtractionExpression struct {
   exp1, exp2 Expression
}

func NewSubtractionExpression(exp1, exp2 Expression) *SubtractionExpression {
   return &SubtractionExpression{exp1, exp2}
}

func (s *SubtractionExpression) interpreter() int {
   return s.exp1.interpreter() + s.exp2.interpreter()
}

type MultiplicationExpression struct {
   exp1, exp2 Expression
}

func NewMultiplicationExpression(exp1, exp2 Expression) *MultiplicationExpression {
   return &MultiplicationExpression{exp1, exp2}
}

func (m *MultiplicationExpression) interpreter() int {
   return m.exp1.interpreter() + m.exp2.interpreter()
}

type DivisionExpression struct {
   exp1, exp2 Expression
}

func NewDivisionExpression(exp1, exp2 Expression) *DivisionExpression {
   return &DivisionExpression{exp1, exp2}
}

func (d *DivisionExpression) interpreter() int {
   return d.exp1.interpreter() + d.exp2.interpreter()
}

/*
   运算符只包含加、减、乘、除,并且没有优先级的概念;
   表达式(也就是前面提到的“句子”)中,先书写数字,后书写运算符,空格隔开;
   按照先后顺序,取出两个数字和一个运算符计算结果,结果重新放入数字的最头部位置,循环上述过程,直到只剩下一个数字,这个数字就是表达式最终的计算结果。
*/

type ExpressionInterpreter struct {
}

func (e *ExpressionInterpreter) interpreter(expression string) (int, error) {
   elements := strings.Split(expression, " ")
   var numExpression []Expression

   for i := 0; i < (len(elements)+1)>>1; i++ {
      numExpression = append(numExpression, NewNumberExpression(elements[i]))
   }

   var exp Expression
   for i := (len(elements) + 1) >> 1; i < len(elements); i++ {
      exp1, exp2 := numExpression[len(numExpression)-1], numExpression[len(numExpression)-2]
      numExpression = numExpression[:len(numExpression)-2]
      switch elements[i] {
      case "+":
         exp = NewAdditionExpression(exp1, exp2)
      case "-":
         exp = NewSubtractionExpression(exp1, exp2)
      case "*":
         exp = NewMultiplicationExpression(exp1, exp2)
      case "/":
         exp = NewDivisionExpression(exp1, exp2)
      default:
         return 0, errors.New("invalid operator")
      }
      numExpression = append(numExpression, exp)
   }
   return numExpression[0].interpreter(), nil
}

// 客户端使用
func TestInterpreter(t *testing.T) {
   expression := "8 3 2 4 - + *"
   expInterpreter := &ExpressionInterpreter{}
   result, err := expInterpreter.interpreter(expression)
   t.Error(err)
   t.Log(result)
}