结构图
角色
- 抽象表达式(AbstractExpression)角色:声明一个执行操作的接口。
- 终结符表达式(TerminalExpression)角色:。实现抽象表达式接口。此处为一般语句。
- 非终结符表达式(NonterminalExpression)角色:实现抽象表达式接口。此处为循环语句。
- 环境(Context)角色:提供解析器之外的一些全局信息。
动机
在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现。如果使用普通的编程方式来实现将面临非常频繁的变化。在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。
意图
给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子。
示意性代码
![](/Images/OutliningIndicators/ContractedBlock.gif)
示意性代码
'MainApp test application
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class MainAppClass MainApp
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub Main()Sub Main()
Dim context As New Context
'Usually a tree
Dim list As New List(Of AbstractExpression)
'Populate 'abstract syntax tree'
list.Add(New TerminalExpression())
list.Add(New NonterminalExpression())
list.Add(New TerminalExpression())
list.Add(New TerminalExpression())
![](/Images/OutliningIndicators/InBlock.gif)
'Interpret
For Each exp As AbstractExpression In list
exp.Interpret(context)
Next
'Wait for user
Console.ReadLine()
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
'"Context"
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class ContextClass Context
End Class
![](/Images/OutliningIndicators/None.gif)
'"AbstractExpression"
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public MustInherit Class AbstractExpressionClass AbstractExpression
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public MustOverride Sub Interpret()Sub Interpret(ByVal context As Context)
End Class
![](/Images/OutliningIndicators/None.gif)
'"TerminalExpression"
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class TerminalExpressionClass TerminalExpression
Inherits AbstractExpression
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overrides Sub Interpret()Sub Interpret(ByVal context As Context)
Console.WriteLine("Called TerminalExpression.Interpret")
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
'"NonterminalExpression"
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class NonterminalExpressionClass NonterminalExpression
Inherits AbstractExpression
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overrides Sub Interpret()Sub Interpret(ByVal context As Context)
Console.WriteLine("Called NonterminalExpression.Interpret")
End Sub
End Class
一个实例
下面的代码演示利用解释器将罗马数字转化为阿拉伯数字。
![](/Images/OutliningIndicators/ContractedBlock.gif)
实例代码
Imports System
Imports System.Collections
![](/Images/OutliningIndicators/None.gif)
' MainApp test application
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class MainAppClass MainApp
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Shared Sub Main()Sub Main()
Dim roman As String = "MCMXXVIII"
Dim context As New Context(roman)
![](/Images/OutliningIndicators/InBlock.gif)
'Build the 'parse tree'
Dim tree As New ArrayList()
tree.Add(New ThousandExpression())
tree.Add(New HundredExpression())
tree.Add(New TenExpression())
tree.Add(New OneExpression())
![](/Images/OutliningIndicators/InBlock.gif)
' Interpret
For Each exp As Expression In tree
exp.Interpret(context)
Next
![](/Images/OutliningIndicators/InBlock.gif)
Console.WriteLine("{0} = {1}", roman, context.Output)
![](/Images/OutliningIndicators/InBlock.gif)
' Wait for user
Console.Read()
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
' "Context"
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class ContextClass Context
Private m_input As String
Private m_output As Integer
![](/Images/OutliningIndicators/InBlock.gif)
' Constructor
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub New()Sub New(ByVal input As String)
Me.m_input = input
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
' Properties
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Property Input()Property Input() As String
Get
Return m_input
End Get
Set(ByVal value As String)
m_input = value
End Set
End Property
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Property Output()Property Output() As Integer
Get
Return m_output
End Get
Set(ByVal value As Integer)
m_output = value
End Set
End Property
End Class
![](/Images/OutliningIndicators/None.gif)
' "AbstractExpression"
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public MustInherit Class ExpressionClass Expression
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub Interpret()Sub Interpret(ByVal context As Context)
If context.Input.Length = 0 Then
Return
End If
![](/Images/OutliningIndicators/InBlock.gif)
If context.Input.StartsWith(Nine()) Then
context.Output += (9 * Multiplier())
context.Input = context.Input.Substring(2)
ElseIf context.Input.StartsWith(Four()) Then
context.Output += (4 * Multiplier())
context.Input = context.Input.Substring(2)
ElseIf context.Input.StartsWith(Five()) Then
context.Output += (5 * Multiplier())
context.Input = context.Input.Substring(1)
End If
![](/Images/OutliningIndicators/InBlock.gif)
While context.Input.StartsWith(One())
context.Output += (1 * Multiplier())
context.Input = context.Input.Substring(1)
End While
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public MustOverride Function One()Function One() As String
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public MustOverride Function Four()Function Four() As String
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public MustOverride Function Five()Function Five() As String
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public MustOverride Function Nine()Function Nine() As String
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public MustOverride Function Multiplier()Function Multiplier() As Integer
End Class
![](/Images/OutliningIndicators/None.gif)
' Thousand checks for the Roman Numeral M
' "TerminalExpression"
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class ThousandExpressionClass ThousandExpression
Inherits Expression
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function One()Function One() As String
Return "M"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Four()Function Four() As String
Return " "
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Five()Function Five() As String
Return " "
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Nine()Function Nine() As String
Return " "
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Multiplier()Function Multiplier() As Integer
Return 1000
End Function
End Class
![](/Images/OutliningIndicators/None.gif)
' Hundred checks C, CD, D or CM
' "TerminalExpression"
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class HundredExpressionClass HundredExpression
Inherits Expression
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function One()Function One() As String
Return "C"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Four()Function Four() As String
Return "CD"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Five()Function Five() As String
Return "D"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Nine()Function Nine() As String
Return "CM"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Multiplier()Function Multiplier() As Integer
Return 100
End Function
End Class
![](/Images/OutliningIndicators/None.gif)
' Ten checks for X, XL, L and XC
' "TerminalExpression"
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class TenExpressionClass TenExpression
Inherits Expression
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function One()Function One() As String
Return "X"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Four()Function Four() As String
Return "XL"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Five()Function Five() As String
Return "L"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Nine()Function Nine() As String
Return "XC"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Multiplier()Function Multiplier() As Integer
Return 10
End Function
End Class
![](/Images/OutliningIndicators/None.gif)
' One checks for I, II, III, IV, V, VI, VI, VII, VIII, IX
' "TerminalExpression"
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class OneExpressionClass OneExpression
Inherits Expression
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function One()Function One() As String
Return "I"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Four()Function Four() As String
Return "IV"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Five()Function Five() As String
Return "V"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Nine()Function Nine() As String
Return "IX"
End Function
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overloads Overrides Function Multiplier()Function Multiplier() As Integer
Return 1
End Function
End Class
Chain of Responsibility模式的几个要点:
1、Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式。
2、使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法。
3、Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具。
我的理解
封装特定领域变化,支持领域问题的频繁变化。
参考资料
《C#面向对象设计模式纵横谈系列课程(16)》 李建中老师