Click here to Skip to main content
15,885,546 members
Articles / Programming Languages / Visual Basic

Using the Specification Design Pattern

Rate me:
Please Sign up or sign in to vote.
3.93/5 (4 votes)
5 Apr 2009CPOL3 min read 25.9K   179   12  
The final part of a four part series of articles on the Specification Design Pattern.
Public MustInherit Class Specification(Of T)

#Region "Declarations"
    Private AndSpec As Specification(Of T)
    Private OrSpec As Specification(Of T)
    Private IsNegated As Boolean
#End Region

#Region "Must Override"
    Protected MustOverride Function SpecificationRule(ByVal obj As T) As Boolean
#End Region

#Region "Public Methods"
    Public Function IsSatisfiedBy(ByVal obj As T) As Boolean

        ' Test this Spec
        Dim blnIsSatisfied As Boolean = SpecificationRule(obj)

        ' Test the AND Branch of the Tree
        If Not AndSpec Is Nothing Then
            blnIsSatisfied = blnIsSatisfied And AndSpec.IsSatisfiedBy(obj)
        End If

        ' Test the OR Branch of the Tree
        If Not OrSpec Is Nothing Then
            blnIsSatisfied = blnIsSatisfied Or OrSpec.IsSatisfiedBy(obj)
        End If

        ' Apply the Not Flag
        blnIsSatisfied = blnIsSatisfied Xor IsNegated

        Return blnIsSatisfied
    End Function
#End Region

#Region "Operators"
    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
#End Region

#Region "Private"
    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 any existing spec
        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

    Private Sub SetNot(ByVal value As Boolean)
        IsNegated = value
    End Sub

    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
#End Region

End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Ireland Ireland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions