这次合作机房收费系统时,经过思考,在上下机那儿觉得既可以用状态模式还可以用观察者模式模式。
观察者模式:(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)他定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
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
在计算上机消费时加上了策略模式,这里就不介绍了。