在做机房重构时,我们会在学生上下机计算学生上机时间时,会出现消费时间随着基本数据设定表中的数据变化而变化,这里不仅仅是数据的变化,还包括不同时间段内消费时间具体确定问题。主要分为三个时间段的计算
以上是主要涉及到状态模式的代码,其实通过对比,我们发现大部分是一样的,只是在context类中(即状态模式的work类)需要把我们实际要用到的参数进行声明。当然可以直接声明公开变量,而省去属性的声明。在客户端直接进行调用就可以了。
1.准备时间:即在此时间段内,消费金额为0
2.至少上机时间:如果上机时间超过了准备时间,但是少于至少上机时间,那么此时消费时间为至少上机时间
3.按正常消费时间来算:此时,消费时间大于至少上机时间后,则按照正常时间来算
通过对业务的分析,我们发现在不同时间段,最终的消费时间的计算方式是不一样的。如果我们就这样直接一条条分析的话,会出现很多if.....else语句,计算过程还会很复杂,这可不是什么好兆头。于是根据23设计模式中特点进行分析,发现使用状态模式或者指责链模式是可以解决分段处理的问题的,这两个模式的使用基本上是一样的,只是在职责链模式需要在客户端来定义下一个执行的具体子类,而状态模式直接定义在了正在执行的子类中。
具体实现如下:
Public MustInherit Class TimePeriod
''' <summary>
''' 计算消费时间的虚方法
''' </summary>
''' <remarks></remarks>
Public MustOverride Sub CountTime(ByVal time As TimeState)
End Class
‘准备时间子类Public Class ReadyTime : Inherits TimePeriod
''' <summary>
''' 准备时间的计算
''' </summary>
''' <param name="time">TimeState对象</param>
''' <remarks></remarks>
Public Overrides Sub CountTime(time As TimeState)
If time.costTime < time.stuReadyTime Then
time.costTime = 0
Else
time.SetNextTimePeriod(New LeastTime()) '设置下一个时间段子类为至少上机时间
time.AllCostTime()
End If
End Sub
End Class
’至少上机时间子类
Public Class LeastTime : Inherits TimePeriod
''' <summary>
'''实现至少上机时间的计算
''' </summary>
''' <param name="time">TimeState对象</param>
''' <remarks></remarks>
Public Overrides Sub CountTime(time As TimeState)
If time.costTime <= time.stuLeastTime Then '如果小于最少上机时间
time.costTime = time.stuLeastTime
Else
time.SetNextTimePeriod(New PerAddTime()) ’设置下一个时间段子类为正常消费时间段
time.AllCostTime()
End If
End Sub
End Class
‘正常消费时间子类,即按正常增长时间计算
Public Class PerAddTime : Inherits TimePeriod
''' <summary>
''' 大于至少消费时间后,按正常消费时间计算
''' </summary>
''' <param name="time">引用timeState的一个对象</param>
''' <remarks></remarks>
Public Overrides Sub CountTime(time As TimeState)
'如果消费时间大于最低消费时间
If time.costTime > time.stuLeastTime Then
time.costTime = time.costTime
End If
End Sub
End Class
’TimeState类,相当于状态模式中的work类,其中定义一个构造方法,来实现最初时间段的选择。构造方法在执行类时,会同时执行构造方法Public Class TimeState
Private timeCurrent As TimePeriod '先定义一个时间状态
Public Sub New()<span style="font-family: Arial; ">'定义一个构造方法,来初始化消费时间的时间段,最少为准备时间段</span>
timeCurrent = New ReadyTime() '初始化消费时间段
End Sub
'定义消费时间变量和属性
Private cost_Time As Decimal
''' <summary>
''' 消费时间属性,即为学生上下机记录中的消费时间
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property costTime As Decimal
Set(value As Decimal)
cost_Time = value
End Set
Get
Return cost_Time
End Get
End Property
'定义一个表示数据信息实体中的准备时间
Private stuReady_Time As Decimal
Public Property stuReadyTime() As Decimal
Set(value As Decimal)
stuReady_Time = value
End Set
Get
Return stuReady_Time
End Get
End Property
'定义一个表示基本数据信息中最少花费时间的属性
Private stuLeast_Time As Decimal
Public Property stuLeastTime As Decimal
Set(value As Decimal)
stuLeast_Time = value
End Set
Get
Return stuLeast_Time
End Get
End Property
'定义一个方法,来设置接下来的时间状态,即消费时间区段
Public Sub SetNextTimePeriod(ByVal nexttime As TimePeriod)
timeCurrent = nexttime '指明下一个消费时间段
End Sub
'定义返回消费时间的方法
Public Sub AllCostTime()
timeCurrent.CountTime(Me)
End Sub
End Class
以上是主要涉及到状态模式的代码,其实通过对比,我们发现大部分是一样的,只是在context类中(即状态模式的work类)需要把我们实际要用到的参数进行声明。当然可以直接声明公开变量,而省去属性的声明。在客户端直接进行调用就可以了。
具体参数的获得略。依个人方法而定
'利用状态模式,先实例化一个TimeState
Dim work As New BLL.TimeState
work.AllCostTime()
txtConsumeTime.Text = work.costTime '利用状态模式获得消费时间,显示消费时间
通过这样,我们可以发现,在U层除了需要为所需要参数进行赋值外,就只剩下上面这短短的几行代码,就完全可以将消费时间这个功能实现。感觉舒服多了吧!
通过机房重构对设计模式的运用,发现只要去应用,设计模式还是很容易接受的,而且写出的代码感觉还是很舒服的。对学习过得知识,在这个过程中努力去应用!