天天看點

機房收費系統之狀态模式

  這次合作機房收費系統時,經過思考,在上下機那兒覺得既可以用狀态模式還可以用觀察者模式模式。

  觀察者模式:(有時又被稱為釋出-訂閱模式、模型-視圖模式、源-收聽者模式或從屬者模式)他定義一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀态發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。

UML圖:

機房收費系統之狀态模式

  抽象被觀察者提供一個借口讓觀察者進行添加和删除觀察者。

    添加(Attach):新增觀察者,一追蹤目标對象的變化。

    删除(Detach):将已有的觀察者删除。

    通知(Notify):利用觀察者提供的更新函數來通知此目标已經産生變化。

  抽象觀察者有一個虛拟的更新(Update)方法,每天具體的觀察者要實作自己的更新方法。當目标對象改變時,會呼叫自己的通知函數來通知給每一個觀察者,觀察者實作自己的更新方法。

  機房合作時上機、下機和強制下機可以用觀察者模式。上機、下機和強制下機時具體的被觀察者,判斷卡是否存在,卡餘額是否足夠,卡是否正在上機等都是具體的觀察者。這裡為了練習,上機我用了甯外一個模式。下機、強制下機用觀察者模式的UML圖:

機房收費系統之狀态模式
  具體被觀察者下機類的代碼:

'觀察者清單
    ''Private ilist As IList(Of ObserverBLL)
    Private ilist As IList(Of ObserverBLL) = New List(Of ObserverBLL)

    ''' <summary>
    ''' 添加觀察者
    ''' </summary>
    ''' <param name="observer">抽象觀察者類</param>
    Public Overrides Sub Attach(ByVal observer As ObserverBLL)
        ilist.Add(observer)
    End Sub

    ''' <summary>
    ''' 去除觀察者
    ''' </summary>
    ''' <param name="observer">抽象觀察者類</param>
    Public Overrides Sub Detach(ByVal observer As ObserverBLL)
        ilist.Remove(observer)
    End Sub

    ''' <summary>
    ''' 通知觀察者
    ''' </summary>
    Public Overrides Sub Notify(ByVal encard As cardentity)
        For Each observer As ObserverBLL In ilist
            observer.Update(encard)
        Next

    End Sub      

  具體觀察者代碼:

  卡是否存在:

''' <summary>
    ''' 更新,檢視卡是否存在
    ''' </summary>
    ''' <param name="enCard">卡号</param>
    Public Overrides Sub Update(ByVal enCard As CardEntity)
        Dim dataAccess As Factory.FactoryReflex                     '定義一個工廠對象
        dataAccess = Factory.FactoryReflex.GetInstance()            '執行個體化工廠對象

        Dim icard As ICard                                          '定義一個接口
        icard = dataAccess.CreateICard()                            '建立接口
        Dim dtCard As New DataTable                                 '定義一個datatable對象
        dtCard = icard.SelectCardUse(enCard)                      '調用D層中查詢卡的方法
        '判斷該卡是否存在
        If dtCard.Rows.Count = 0 Then
            Throw New Exception("該卡不存在!")
        End If
    End Sub      

  是否正在上機:

''' <summary>
    ''' (卡号),将enCard實體的卡号指派個他
    ''' </summary>
    Private enLineRecord As New LineRecordEntity

    ''' <summary>
    ''' 更新,查詢該卡是否正在上機
    ''' </summary>
    ''' <param name="enCard">卡号</param>
    Public Overrides Sub Update(ByVal enCard As CardEntity)
        Dim dataAccess As Factory.FactoryReflex                     '定義一個工廠對象
        dataAccess = Factory.FactoryReflex.GetInstance()            '執行個體化工廠對象

        Dim ilineRecord As ILineRecord                              '定義一個接口
        ilineRecord = dataAccess.CreateILine()                      '建立接口
        Dim dtLineRecord As New DataTable
        'Dim enLineRecord As New LineRecordEntity
        enLineRecord.ProCardId = enCard.ProCardId
        dtLineRecord = ilineRecord.SelectIsOnLine(enLineRecord)                   '查詢該卡是否正在上機
        '判斷該卡是否正在上機
        If dtLineRecord.Rows.Count = 0 Then
            Throw New Exception("該卡沒有上機!")
        End If
    End Sub      

  更新上機記錄: 

''' <summary>
    ''' 更新,将上機記錄更新到表T_LineRecord
    ''' </summary>
    ''' <param name="enCard">卡号</param>
    Public Overrides Sub Update(ByVal enCard As CardEntity)
        Dim dataAccess As Factory.FactoryReflex                     '定義一個工廠對象
        dataAccess = Factory.FactoryReflex.GetInstance()            '執行個體化工廠對象

        Dim ilineRecord As ILineRecord                              '定義一個接口
        ilineRecord = dataAccess.CreateILine()                      '建立接口
        Dim dtLineRecord As New DataTable
        enLineRecord.ProCardId = enCard.ProCardId
        dtLineRecord = ilineRecord.SelectIsOnLine(enLineRecord)     '查詢上機記錄

        Dim offDate As Date = CDate(Format(Now(), "yyyy/M/d"))       '下機日期
        Dim offTime As String = Format(Now(), "HH:mm")             '下機時間
        Dim spentTime As Integer
        spentTime = CInt(DateDiff(DateInterval.Minute, CDate(dtLineRecord.Rows(0).Item("上機時間").ToString), CDate(offTime)))

        '讀取使用者類型
        Dim type As String                                         '存放使用者類型
        Dim icard As ICard                                          '定義一個接口
        icard = dataAccess.CreateICard()                            '建立接口
        Dim dtCard As New DataTable                                 '定義一個datatable對象
        dtCard = icard.SelectCardUse(enCard)                      '調用D層中查詢卡的方法
        type = dtCard.Rows(0).Item("卡類型").ToString             '使用者類型

        '調用計算上機消費的方法

        Dim cashContext As New CashContextBLL(spentTime, type)
        cashContext.ProStrTime = spentTime
        cashContext.ProType = type
        spentCash = cashContext.GetResult()
        leaveCash = CSng(dtCard.Rows(0).Item("卡内餘額").ToString) - spentCash

        '給上機記錄實體指派
        enLineRecord.ProOffDate = offDate
        enLineRecord.ProOffTime = offTime
        enLineRecord.ProConsumeTime = spentTime
        enLineRecord.ProConsumeCash = spentCash
        enLineRecord.ProOnDate = CDate(dtLineRecord.Rows(0).Item("上機日期").ToString)
        enLineRecord.ProOnTime = dtLineRecord.Rows(0).Item("上機時間").ToString
        enLineRecord.ProLeaveCash = leaveCash

        '将記錄更新到資料庫上機記錄表裡
        Dim bln As Boolean
        bln = ilineRecord.UpdateOnLine(enLineRecord)
    End Sub      

  更新卡餘額:

''' <summary>
    ''' 更新,更新卡的餘額,餘額從類ModifyLineRecordBLL中讀取
    ''' </summary>
    ''' <param name="enCard">卡号</param>
    Public Overrides Sub Update(ByVal enCard As CardEntity)
        Dim dataAccess As Factory.FactoryReflex                     '定義一個工廠對象
        dataAccess = Factory.FactoryReflex.GetInstance()            '執行個體化工廠對象

        Dim icard As ICard                                          '定義一個接口
        icard = dataAccess.CreateICard()                            '建立接口
        Dim bln As Boolean
        enCard.ProCash = ModifyLineRecordBLL.leaveCash
        bln = icard.UpdateCardCash(enCard)

    End Sub      

  在計算上機消費時加上了政策模式,這裡就不介紹了。

上一篇: 添加水印