实战练习之--状态模式

   在第一遍学习大话设计模式的时候,写过关于状态模式的博客。不过那个时候的素材主要来自于课本,理解的内容也是书上的例子,以“看懂”为主要目的。但是在这次机房收费系统合作版的实战中,我需要以“会用”为主要目的了,当然,理解的也会有所深刻。

   此次我把状态模式加在上学生下机处,主要为了计算消费金额。大致思路为:(此种思路主要针对于网吧使用的收费系统,因为学校机房可以玩通宵的还是比较少的。)首先,将上机状态分为两种:一种是白天状态,另一种那个就是夜间状态。夜间状态的消费金额为固定,白天状态的消费金额则是变化的,因消费时间和用户类型而异。下面是机房收费系统中状态模式的结构图:


   

   代码如下:

 

   一、抽象状态类此类定义一个接口,封装了与Context中一个特定状态有关的行为。

''' <summary>
''' 抽像状态类
''' </summary>
Public MustInheritClass State
    ''' <summary>
    ''' 消费金额
    ''' </summary>
    ''' <paramname="enStudent">传递过来上机时间。</param>
    Public MustOverride Function Handle(ByValenStudent As Entity.LineEntity, ByVal context As Context) As String
End Class

 

   二、状态子类:夜间状态,此处取出上机时间中的小时值,判断用户处于哪儿中状态,如果符合当前子类状态,则返回当前状态,否则,进入预先设定的下一状态:白天模式。(注意状态子类中需要指定下一状态)

''' <summary>
''' 夜间状态'''</summary>
Public ClassNightState
    Inherits BLL.State
 
    ''' <summary>
    ''' 消费金额
    ''' </summary>
    ''' <paramname="enStudent">传递过来上机时间。</param>
    ''' <paramname="context">状态的作用对象。</param>
    Public Overloads Overrides FunctionHandle(enStudent As Entity.LineEntity, context As Context) As String
        Dim SpendMoney As String
        Dim onTime As System.DateTime
        Dim hour As Integer = onTime.Hour
        '取出上机时间中的小时值
        onTime =System.DateTime.Parse(CStr(enStudent.OnTime))
        '判断用户是何时上机,如果是夜间上机的话,返回“夜间模式”
        If hour < 6 Or hour > 22 Then
            Return "夜间模式"
        Else
            context.SetState(New DayState)
        End If
 
    End Function
End Class

 

   三、状态子类:同上

''' <summary>
''' 白天模式'''</summary>
Public ClassDayState
    Inherits BLL.State
 
    ''' <summary>
    ''' 消费金额
    ''' </summary>
    ''' <paramname="enStudent">传递过来上机时间。</param>
    ''' <paramname="context">状态作用对象</param>
    Public Overloads Overrides FunctionHandle(enStudent As Entity.LineEntity, context As Context) As String
        Dim onTime As System.DateTime
        Dim hour As Integer = onTime.Hour
        '取出上机时间中的小时值
        onTime =System.DateTime.Parse(CStr(enStudent.OnTime))
        '判断用户是何时上机,如果是夜间上机的话,消费时间为实际消费时间,消费金额固定为15元
        If hour > 6 And hour < 22 Then
            Return "白天模式"
        Else
            context.SetState(New NightState)
        End If
    End Function
End Class

 

   四、Context。首先,它需要定义一个初始状态,再此我们定义DayState也就是白天模式为默认初始状态,并且需要设置一个“钟点”属性,用来判断当前状态和设置最新状态。

 

''' <summary>
'''Context类,定义当前的状态
''' </summary>
'''<remarks></remarks>
Public Class Context
 
    Private currentState As State
    '定义Context的初始状态--为白天模式
    Public Sub New(ByVal State As State)
        currentState = New DayState
    End Sub
 
    Private hour As Double
    '"钟点"属性,状态转换的依据
    Public Property _Hour() As Double
        Get
            Return hour
        End Get
        Set(ByVal value As Double)
            hour = value
        End Set
    End Property
 
    ''' <summary>
    ''' 设置工作状态
    ''' </summary>
    ''' <paramname="state">工作状态</param>
    ''' <remarks></remarks>
    Public Sub SetState(ByVal state As State)
        currentState = state
    End Sub
 
    ''' <summary>
    ''' 维护一个ConcreteState子类的实例,这个实例定义当前的状态。
    ''' </summary>
    Public Function Request(ByVal enStudent AsEntity.LineEntity) As String
        '对请求做处理,并设置下一状态
        Return currentState.Handle(enStudent,Me)
    End Function
 
End Class

 

   五、客户端代码:此处,实例化Context类,并且设置Context的初始状态为:白天状态,然后根据U层传来的学生上机信息实体类中的上机时间,来判断属于那种状态。如果是白天状态,则调用策略模式中的相应具体算法类(此处咱不强调),根据消费时间和用户类型,计算出消费金额;反之如果是夜间状态,暂定消费金额固定,为15元。

 

   ''' <summary>
    ''' 不同的用户收取的金额。
    ''' </summary>
    ''' <paramname="enStudent">学生上机实体类</param>
    Public Function GetResutl(ByVal enStudentAs Entity.LineEntity) As Double
        Dim DayState As New DayState
        Dim stateType As NewContext(DayState)  '设置Context的初始状态为:白天模式
        Dim NowState As String
        Dim SpendMoney As Double
        NowState =stateType.Request(enStudent)  '根据实体中的上机时间属性,来判断状态类型
 
        '如果是夜间模式,消费金额恒为15元;如果为白天模式,消费金额依据卡类型不同而不同
        If NowState = "白天模式" Then
            '固定用户调用FixUser具体算法类
            IfenStudent.CardType = "固定用户" Then
                Dim fixUser As New FixUser
                SpendMoney =fixUser.AcceptCash(enStudent)
            Else
                '临时用户调用TempUser具体算法类
                Dim tempUser As New TempUser
                SpendMoney =tempUser.AcceptCash(enStudent)
            End If
        Else
            SpendMoney = 15
        End If
        Return SpendMoney
    End Function

 

   这样,我们可以实现代码扩展的灵活性,我们可以通过增加不同的状态子类来增加不同的状态,不再需要过丑和过长的分支判断了。当然了,这样也实现了好代码的可开放-封闭原则。

评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值