一、基础篇
含义:状态模式(State):当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是党控制一个对象状态转换的条件过于复杂的情况,把状态的判断转移到表示不同状态的一系列类当中,从而实现复杂的判断逻辑简化的目的。同样的,当判断需要增加的时候,也可以将状态类增加,减少了多分支情况下的修改量,也符合了软件开发中的‘开放—封闭原则’
结构图:
优点与用处:将特定的状态相关的行为局部化,并且将不同状态的行为分割开来。简单来说,就是为了消除庞大的条件分支语句。因为大的分支判断会使得系统变得复杂而难以修改和扩展。这就类似我们中国四大发明中的印刷术一样。复杂的分支判断就像是雕版印刷术,而状态模式就像北宋时期发明的活字印刷术,从而使得整个业务系统变得容易扩展和维护
二、应用篇
在机房收费系统中,如果用面向过程的思想来说,有很多复杂的业务逻辑判断分支结构,例如学生上机。对于学生上机,首先我们需要判断用户是否存在,其次判断用户是否已经上机,再次,判断用户余额是否大于系统最低上机金额要求,最后就是将学生上机信息添加到正在上机表中。
抽象类:
''' <summary>
''' 抽象状态类,让其他各个状态类去继承
''' </summary>
''' <remarks>提供一个上机方法,让其他子类进行继承</remarks>
Public Class State
Public Overridable Sub Online(ByVal CardInfo As Entity.StudentInfoEntity, ByVal OnLine As Entity.StuOnlineEntity, ByVal OnlineBLL As BLL.OnlineBLL)
End Sub
End Class
判断用户是否存在子状态:
''' <summary>
''' 判断用户是否注册子状态
''' </summary>
''' <remarks></remarks>
Public Class IsNull
Inherits BLL.State
Dim dataAccess As New Factory.DataAccess '创建工厂
Dim IStudentInfo As IDAL.IStudentInfo '定义接口
Public Overrides Sub Online(ByVal CardInfo As Entity.StudentInfoEntity, ByVal OnLine As Entity.StuOnlineEntity, ByVal OnlineBLL As BLL.OnlineBLL)
IStudentInfo = dataAccess.CreateStudent '创建接口
If IStudentInfo.SelectStudent(CardInfo).Rows.Count = 0 Then
Throw New Exception("该用户尚未注册,请注册之后再进行上机操作")
Else
OnlineBLL.SetState(New IsOnline) '如果注册,返回下个状态——判断用户是否上机子状态
OnlineBLL.StuOnLine(CardInfo, OnLine, OnlineBLL)
End If
End Sub
End Class
判断用户是否上机子状态:
''' <summary>
''' 判断用户是否上机子状态
''' </summary>
''' <remarks></remarks>
Public Class IsOnline
Inherits BLL.State
Dim dataAccess As New Factory.DataAccess '创建工厂
Dim IOnlineInfo As IDAL.IOnline '定义接口
Public Overrides Sub Online(ByVal CardInfo As Entity.StudentInfoEntity, ByVal OnLine As Entity.StuOnlineEntity, ByVal OnlineBLL As BLL.OnlineBLL)
IOnlineInfo = dataAccess.CreateOnline '创建接口
If IOnlineInfo.SelectOnlineStu(OnLine).Rows.Count <> 0 Then
Throw New Exception("该卡号正在正在上机,请更换其他卡号进行上机操作")
Else
OnlineBLL.SetState(New IsCashEnough) '如果没有上机,转入到下个状态——判断用户余额是否充足
OnlineBLL.StuOnLine(CardInfo, OnLine, OnlineBLL)
End If
End Sub
End Class
判断用户余额是否充足子状态:
''' <summary>
''' 判断用户金额是否充足子状态
''' </summary>
''' <remarks></remarks>
Public Class IsCashEnough
Inherits BLL.State
Dim dataAccess As New Factory.DataAccess '定义工厂
Dim IStuInfo As IDAL.IStudentInfo '定义接口
Dim IBasicData As IDAL.IBasicDataset '定义接口
Public Overrides Sub Online(CardInfo As Entity.StudentInfoEntity, OnLine As Entity.StuOnlineEntity, OnlineBLL As OnlineBLL)
IStuInfo = dataAccess.CreateStudent '创建接口
IBasicData = dataAccess.CreateBasicData '创建接口
'用户金额充足,进入下一个状态——判断用户是否添加信息成功,否则抛出异常
If Trim(IStuInfo.SelectStudent(CardInfo).Rows(0).Item("Cash")) > Trim(IBasicData.SelectBasicData.Rows(0).Item("limitCash")) Then
OnlineBLL.SetState(New IsAddOnline())
OnlineBLL.StuOnLine(CardInfo, OnLine, OnlineBLL)
Else
Throw New Exception("用户余额不足,请充值之后再进行上机操作")
End If
End Sub
End Class
判断添加用户上机信息是否成功:
''' <summary>
''' 重读状态基类,判断是否添加上机信息成功
''' </summary>
''' <remarks></remarks>
Public Class IsAddOnline
Inherits BLL.State
Dim dataAccess As New Factory.DataAccess
Dim IOnline As IDAL.IOnline
Dim IStudentInfo As IDAL.IStudentInfo
Dim bolAddOnline As Boolean
Public Overrides Sub Online(CardInfo As Entity.StudentInfoEntity, OnLine As Entity.StuOnlineEntity, OnlineBLL As OnlineBLL)
IStudentInfo = dataAccess.CreateStudent
Dim dtStuInfo As DataTable
dtStuInfo = IStudentInfo.SelectStudent(CardInfo)
OnLine.StuID = Trim(dtStuInfo.Rows(0).Item(1))
OnLine.StuName = Trim(dtStuInfo.Rows(0).Item(2))
OnLine.StuDepartment = Trim(dtStuInfo.Rows(0).Item(4))
OnLine.StuSex = Trim(dtStuInfo.Rows(0).Item(3))
OnLine.StuOndate = Date.Today '学生上机日期
OnLine.StuOntime = TimeOfDay '学生上机时间
OnLine.ComputerID = Environment.MachineName '学生上机机器号
IOnline = dataAccess.CreateOnline
bolAddOnline = IOnline.AddStuOnline(OnLine)
End Sub
End Class
客户端窗体代码:
Dim onlinebll As New BLL.OnlineBLL
Dim entityStuInfo As New Entity.StudentInfoEntity
Dim entityLineInfo As New Entity.StuOnlineEntity
entityStuInfo.StuCardID = Trim(txtCardID.Text)
entityLineInfo.StuCardID = Trim(txtCardID.Text)
Try
If onlinebll.StuOnLine(entityStuInfo, entityLineInfo, onlinebll) = False Then
MsgBox("用户上机失败", , "温馨提示")
Else
MsgBox("用户上机成功", , "温馨提示")
End If
Catch ex As Exception
MsgBox(ex.Message.ToString, , "温馨提示")
End Try
三、小结:
对于状态模式,简而言之:可以用来解决复杂的业务逻辑判断,将纷繁复杂的业务判断分支以类的形式封装,根据具体的状态来执行不同的操作,从而实现了软件开发中的’开放——封闭原则‘,即保留了增加分支判断的可能性,也减少了因复杂分支修改过多的麻烦。