首页 > 代码库 > 机房收费系统上下机之观察者模式的尝试

机房收费系统上下机之观察者模式的尝试

       如果读者想在本篇文章中看到观察者模式的巧妙应用,大概有些不可能了。因为这里我只是想把自己的一种思路展现给大家,然后和大家探讨。

背景

       在敲机房收费系统的过程中,都是别人说可能会用到什么模式,然后自己针对这些模式进行思考,然后去模仿书中的例子去用。

       这不,师姐说上下机这里能用观察者模式,然后我就琢磨了一番,只是收获不是很丰硕,貌似也和师姐讲课中的设想不一样。

       我在琢磨使用观察者模式时,已经把系统中和上下机有关的功能实现了。只是在写代码的过程中发现,每次下机,都需要先把正在上机的卡的上机信息查出来(上机时间),然后再更新上下机记录。而且,咱们的系统中有三个地方可以实现下机:主窗体上的下机,选中学生下机,全部学生下机。它们中都有重复的过程。

想法:

        每次单击上机按钮时,就实例化一个Observer类,把该卡的上机信息(卡号,卡类型(固定/临时),上机时间)保存到该对象中,然后在另一个Subject类中有一个泛型集合,只要上机成功,就在List中添加一个Observer类,这样Subject中保存所有的上机的卡对象。

       点击下机按钮时或选中学生下机时,就更改Subject的状态,并调用Subject的Notify方法,通知要下机的观察者更新。       

类图:

         

代码:

  • 主题Subject

Public Class OffLineSubject
    '添加一个观察者的泛型集合
    Private onlineObservers As New List(Of OnLineObserver)

    Private Shared offlineSubject As OffLineSubject
    Private Sub New()

    End Sub
    ''' <summary>
    ''' 单例模式的应用,保证程序中只有一个OffLineSubject的实例
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GetSubjectInstance() As OffLineSubject
        If offlineSubject Is Nothing Then
            offlineSubject = New OffLineSubject
        End If
        Return offlineSubject
    End Function


    '下机日期
    Private _offDate As Date
    Public Property OffDate() As Date
        Get
            Return _offDate
        End Get
        Set(ByVal value As Date)
            _offDate = value
        End Set
    End Property
    '下机时间
    Private _offTime As TimeSpan
    Public Property OffTime() As TimeSpan
        Get
            Return _offTime
        End Get
        Set(ByVal value As TimeSpan)
            _offTime = value
        End Set
    End Property
    '下机方式
    Private _offWay As String
    Public Property OffWay() As String
        Get
            Return _offWay
        End Get
        Set(ByVal value As String)
            _offWay = value
        End Set
    End Property
    '增加上机观察者
    Sub Attach(ByVal onlineObserver As OnLineObserver)
        onlineObservers.Add(onlineObserver)

    End Sub
    '减少上机观察者
    Sub Detach(ByVal onlineObserver As OnLineObserver)
        onlineObservers.Remove(onlineObserver)

    End Sub
    '通知上机观察者,根据上机的卡的卡号来确定具体通知那个上机观察者
    Sub Notify(ByVal key As String)
        Dim i As Integer
        For i = 0 To onlineObservers.Count - 1
            If onlineObservers.Item(i).CardID = key Then
                onlineObservers.Item(i).Update()
            End If
        Next
    End Sub

End Class

  • 观察者Observer

Public Class OnLineObserver


    '添加一个通知者的引用
    Private offSubject As OffLineSubject

    Sub New(ByVal offSubject As OffLineSubject)
        Me.offSubject = offSubject
    End Sub
    Private _cardID As String
    Public Property CardID() As String
        Get
            Return _cardID
        End Get
        Set(ByVal value As String)
            _cardID = value
        End Set
    End Property

    Private _cardType As String
    Public Property CardType() As String
        Get
            Return _cardType
        End Get
        Set(ByVal value As String)
            _cardType = value
        End Set
    End Property

    Private _onTime As TimeSpan
    Public Property OnTime() As TimeSpan
        Get
            Return _onTime
        End Get
        Set(ByVal value As TimeSpan)
            _onTime = value
        End Set
    End Property

    Sub Update()
        Dim enOnOffLineRecord As New Entity.OnOffLineRecordEntity
        Dim bllOnOffLineRecord As New BLL.OnOffLineRecordBLL
        '获得通知者的一些属性(下机方式,下机日期和下机时间)
        enOnOffLineRecord.OffWay = offSubject.OffWay
        enOnOffLineRecord.OffDate = offSubject.OffDate
        enOnOffLineRecord.OffTime = offSubject.OffTime
        '调用策略模式计算消费金额,略
        '……
        '……
        '更新上下机记录
        bllOnOffLineRecord.UpdateOnOffLineRecordBLL(enOnOffLineRecord)

    End Sub

End Class


  • Function OnLine(Byval enCardInfo as Entity.CardInfoEntity)as Boolean

Dim onObserver As OnLineObserver
        Dim systemDate As DateTime = DateTime.Now
        Dim offSubject As OffLineSubject
        '获取唯一的主题通知者实例
        offSubject = OffLineSubject.GetSubjectInstance
        onObserver = New OnLineObserver(offSubject)
        '将上机信息封装
        onObserver.CardID = enCardInfo.CardID
        onObserver.CardType = enCardInfo.CardType
        onObserver.OnTime = systemDate.TimeOfDay
        '在通知者中添加一个观察者
        offSubject.Attach(onObserver)


  • Function OffLine(Byval enCardInfo as Entity.CardInfoEntity) as Boolean

Dim offSubject As OffLineSubject
        offSubject = OffLineSubject.GetSubjectInstance
        offSubject.OffWay = "正常下机"
        'offSubject .OffDate =""
        'offSubject .OffTime =""
        '通知下机
        offSubject.Notify(enCardInfo.CardID)

       以上是我的一个初步设想,但是不知道在程序运行中对内存的消耗的影响,已经在不同的机子上上下机这样是否真的可行。有待进一步的学习和思考。