VB.NET 中的通用规范





5.00/5 (1投票)
关于规范设计模式的四部分系列文章的第三部分。
引言
这是四篇文章系列中的第三篇,讨论规范设计模式以及如何使用 VB.NET 实现它。
- 第 1 部分 - 规范设计模式简介
- 第 2 部分 - 在 VB.NET 中简单实现该模式
- 第 3 部分 - 带有运算符重载的通用规范
- 第 4 部分 - 使用通用规范
背景
规范设计模式由 Eric Evans 创建。他在他的著作《领域驱动设计》中提供了该模式的描述。本系列文章展示了如何使用 VB.NET 实现该模式。
通用规范
IsSatisfiedBy
函数只需要在基础规范类中编写一次。更简单的 SpecificationRule
在我们的具体规范中编写,只需要关注它所接收的候选对象。
使用运算符组合规范的逻辑是在基础规范中的三个函数中实现的。具体规范将从重载的运算符函数中调用这些方法。这将在本系列的第四部分中看到。
Protected Shared Function AndOperator(ByVal a As Specification(Of T), _
ByVal b As Specification(Of T)) As Specification(Of T)
Dim newSpec As Specification(Of T) = a.Copy
newSpec.SetAnd(b.Copy)
Return newSpec
End Function
Protected Shared Function OrOperator(ByVal a As Specification(Of T), _
ByVal b As Specification(Of T)) As Specification(Of T)
Dim newSpec As Specification(Of T) = a.Copy
newSpec.SetOr(b.Copy)
Return newSpec
End Function
Protected Shared Function NotOperator(ByVal a As Specification(Of T)) _
As Specification(Of T)
Dim newSpec As Specification(Of T) = a.Copy
newSpec.SetNot(Not a.IsNegated)
Return newSpec
End Function
这些运算符函数依赖于四个私有函数:SetAnd
、SetOr
、SetNot
和 Copy
。这些函数实现了创建复杂规范组合的实际逻辑。
简单来说,每个规范都有两个分支,每个分支都可以指向另一个规范。当在上面看到的 IsSatisfiedBy
函数中评估规范时,该函数负责评估它所指向的任何规范。这会递归进行,直到评估完所有规范。
SetAnd
和 SetOr
方法被传递一个要加入到现有规范的规范。SetAnd
方法将其附加到 AND 分支,而 SetOr
方法将其附加到 OR 分支。显然,要添加的规范本身可以是包含多个规范的树的根。
Private Sub SetAnd(ByVal spec As Specification(Of T))
' If setting to nothing, set it directly
If spec Is Nothing Then
AndSpec = spec
Exit Sub
End If
' If setting to an actual spec, then attach to the end of any existing spec
If AndSpec Is Nothing Then
' No existing spec, so set directly
AndSpec = spec
Else
' Recursively call SetAnd until we get to the end of the chain of specs
AndSpec.SetAnd(spec)
End If
End Sub
Private Sub SetOr(ByVal spec As Specification(Of T))
' If setting to nothing, set it directly
If spec Is Nothing Then
OrSpec = spec
Exit Sub
End If
' If setting to an actual spec, then attach
' to the end of the existing chain of specs
If OrSpec Is Nothing Then
' No existing spec, so set directly
OrSpec = spec
Else
' Recursively call SetOr until we get to the end of the chain of specs
OrSpec.SetOr(spec)
End If
End Sub
NOT 运算符是一个简单的布尔标志。如果设置了它,则否定规范的结果。
Private Sub SetNot(ByVal value As Boolean)
IsNegated = value
End Sub
我们还需要一个复制函数,可以复制一个规范或一棵规范树。这被 AndOperator
、OrOperator
和 NotOperator
函数使用。
Private Function Copy() As Specification(Of T)
' Copy this spec
Dim newSpec As Specification(Of T)
newSpec = CType(Me.MemberwiseClone, Specification(Of T))
' Clear the andSpec and orSpec so they can be pointed
' at copies of the existing andSpec and orSpec
' After the MemberwiseClone the newSpec points to the same subSpecs
newSpec.SetAnd(Nothing)
newSpec.SetOr(Nothing)
If Not AndSpec Is Nothing Then
newSpec.SetAnd(AndSpec.Copy)
End If
If Not OrSpec Is Nothing Then
newSpec.SetOr(OrSpec.Copy)
End If
Return newSpec
End Function
在本系列的结尾部分,我们将构建一个继承自 Specification 类的 ContainerSpecification
类的新版本。然后,我们将声明一些 ContainerSpecification
并将它们组合起来。