如果读者想在本篇文章中看到观察者模式的巧妙应用,大概有些不可能了。因为这里我只是想把自己的一种思路展现给大家,然后和大家探讨。
背景:
在敲机房收费系统的过程中,都是别人说可能会用到什么模式,然后自己针对这些模式进行思考,然后去模仿书中的例子去用。
这不,师姐说上下机这里能用观察者模式,然后我就琢磨了一番,只是收获不是很丰硕,貌似也和师姐讲课中的设想不一样。
我在琢磨使用观察者模式时,已经把系统中和上下机有关的功能实现了。只是在写代码的过程中发现,每次下机,都需要先把正在上机的卡的上机信息查出来(上机时间),然后再更新上下机记录。而且,咱们的系统中有三个地方可以实现下机:主窗体上的下机,选中学生下机,全部学生下机。它们中都有重复的过程。
想法:
每次单击上机按钮时,就实例化一个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)
以上是我的一个初步设想,但是不知道在程序运行中对内存的消耗的影响,已经在不同的机子上上下机这样是否真的可行。有待进一步的学习和思考。