★☆☆☆☆
给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子。
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
结构图
角色
- 抽象表达式(AbstractExpression)角色:声明一个执行操作的接口。
- 终结符表达式(TerminalExpression)角色:。实现抽象表达式接口。此处为一般语句。
- 非终结符表达式(NonterminalExpression)角色:实现抽象表达式接口。此处为循环语句。
- 环境(Context)角色:提供解析器之外的一些全局信息。
动机
在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现。如果使用普通的编程方式来实现将面临非常频繁的变化。在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。
意图
给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子。
示意性代码

示意性代码
'MainApp test application

Public Class MainAppClass MainApp

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())

'Interpret
For Each exp As AbstractExpression In list
exp.Interpret(context)
Next
'Wait for user
Console.ReadLine()
End Sub
End Class

'"Context"

Public Class ContextClass Context
End Class

'"AbstractExpression"

Public MustInherit Class AbstractExpressionClass AbstractExpression

Public MustOverride Sub Interpret()Sub Interpret(ByVal context As Context)
End Class

'"TerminalExpression"

Public Class TerminalExpressionClass TerminalExpression
Inherits AbstractExpression

Public Overrides Sub Interpret()Sub Interpret(ByVal context As Context)
Console.WriteLine("Called TerminalExpression.Interpret")
End Sub
End Class

'"NonterminalExpression"

Public Class NonterminalExpressionClass NonterminalExpression
Inherits AbstractExpression

Public Overrides Sub Interpret()Sub Interpret(ByVal context As Context)
Console.WriteLine("Called NonterminalExpression.Interpret")
End Sub
End Class
一个实例
下面的代码演示利用解释器将罗马数字转化为阿拉伯数字。

实例代码
Imports System
Imports System.Collections

' MainApp test application

Public Class MainAppClass MainApp

Private Shared Sub Main()Sub Main()
Dim roman As String = "MCMXXVIII"
Dim context As New Context(roman)

'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())

' Interpret
For Each exp As Expression In tree
exp.Interpret(context)
Next

Console.WriteLine("{0} = {1}", roman, context.Output)

' Wait for user
Console.Read()
End Sub
End Class

' "Context"

Public Class ContextClass Context
Private m_input As String
Private m_output As Integer

' Constructor

Public Sub New()Sub New(ByVal input As String)
Me.m_input = input
End Sub

' Properties

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


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

' "AbstractExpression"

Public MustInherit Class ExpressionClass Expression

Public Sub Interpret()Sub Interpret(ByVal context As Context)
If context.Input.Length = 0 Then
Return
End If

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

While context.Input.StartsWith(One())
context.Output += (1 * Multiplier())
context.Input = context.Input.Substring(1)
End While
End Sub


Public MustOverride Function One()Function One() As String

Public MustOverride Function Four()Function Four() As String

Public MustOverride Function Five()Function Five() As String

Public MustOverride Function Nine()Function Nine() As String

Public MustOverride Function Multiplier()Function Multiplier() As Integer
End Class

' Thousand checks for the Roman Numeral M
' "TerminalExpression"

Public Class ThousandExpressionClass ThousandExpression
Inherits Expression

Public Overloads Overrides Function One()Function One() As String
Return "M"
End Function

Public Overloads Overrides Function Four()Function Four() As String
Return " "
End Function

Public Overloads Overrides Function Five()Function Five() As String
Return " "
End Function

Public Overloads Overrides Function Nine()Function Nine() As String
Return " "
End Function

Public Overloads Overrides Function Multiplier()Function Multiplier() As Integer
Return 1000
End Function
End Class

' Hundred checks C, CD, D or CM
' "TerminalExpression"

Public Class HundredExpressionClass HundredExpression
Inherits Expression

Public Overloads Overrides Function One()Function One() As String
Return "C"
End Function

Public Overloads Overrides Function Four()Function Four() As String
Return "CD"
End Function

Public Overloads Overrides Function Five()Function Five() As String
Return "D"
End Function

Public Overloads Overrides Function Nine()Function Nine() As String
Return "CM"
End Function

Public Overloads Overrides Function Multiplier()Function Multiplier() As Integer
Return 100
End Function
End Class

' Ten checks for X, XL, L and XC
' "TerminalExpression"

Public Class TenExpressionClass TenExpression
Inherits Expression

Public Overloads Overrides Function One()Function One() As String
Return "X"
End Function

Public Overloads Overrides Function Four()Function Four() As String
Return "XL"
End Function

Public Overloads Overrides Function Five()Function Five() As String
Return "L"
End Function

Public Overloads Overrides Function Nine()Function Nine() As String
Return "XC"
End Function

Public Overloads Overrides Function Multiplier()Function Multiplier() As Integer
Return 10
End Function
End Class

' One checks for I, II, III, IV, V, VI, VI, VII, VIII, IX
' "TerminalExpression"

Public Class OneExpressionClass OneExpression
Inherits Expression

Public Overloads Overrides Function One()Function One() As String
Return "I"
End Function

Public Overloads Overrides Function Four()Function Four() As String
Return "IV"
End Function

Public Overloads Overrides Function Five()Function Five() As String
Return "V"
End Function

Public Overloads Overrides Function Nine()Function Nine() As String
Return "IX"
End Function

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)》 李建中老师
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通