這次合作機房收費系統時,經過思考,在上下機那兒覺得既可以用狀态模式還可以用觀察者模式模式。
觀察者模式:(有時又被稱為釋出-訂閱模式、模型-視圖模式、源-收聽者模式或從屬者模式)他定義一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀态發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。
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
在計算上機消費時加上了政策模式,這裡就不介紹了。