上篇博客介绍了策略模式的实例使用,这篇博客介绍一下状态模式的实例使用。
1.状态模式是解决什么问题的?
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。说得通俗一点就是消除庞大的条件分支语句。如果这样说状态模式可使用的地方还是很多的,比如登录功能,上下机时都可以。
2.状态模式实例的UML图
在机房收费系统的登录功能中使用状态模式,四个状态(也可以说是条件)用户名是否存在,密码是否正确,用户是否正在工作,更新数据库完成登录。具体实现请看代码。
3.实例代码
LoginBLL类
'' <summary>
''' 定义一个状态变量
''' </summary>
Private current As LogState
''' <summary>
''' 构造函数,初始化开始状态为判断用户名是否存在
''' </summary>
Public Sub New()
current = New UserNameIsExist()
End Sub
''' <summary>
''' 设置状态
''' </summary>
''' <param name="loginstate">传递用户登录过程中的状态</param>
Public Function SetState(ByVal loginstate As LogState) As LogState
current = loginstate '将当前状态值传递给全局变量current
Return current '将设置好的状态值返回
End Function
''' <summary>
''' 登录
''' </summary>
''' <param name="enWork">工作记录实体</param>
''' <param name="enUser">用户实体</param>
''' <returns>登录成功返回true
''' 登录失败返回false</returns>
''' <remarks></remarks>
Public Function Login(ByVal enWork As Entity.WorkEntity, ByVal enUser As Entity.UserEntiity) As Boolean
Dim logins As LoginBLL = New LoginBLL '定义局部变量login 并实例化
Dim flag As Boolean = False '定义布尔类型变量 初始值为false
'调用登陆状态类的方法
Try
LogState.onLog(logins, enWork, enUser)
flag = True '登陆成功
Catch ex As Exception
Throw New Exception(ex.Message) '捕捉登陆异常 ,并将异常抛出
End Try
Return flag '将结果返回
End Function
End Class
logState类:
Public Class LogState
''' <summary>
''' 登录状态
''' </summary>
''' <param name="login">登录</param>
''' <param name="enWork">工作实体</param>
''' <param name="enUser">用户实体</param>
Public Overridable Sub onLog(ByVal login As LoginBLL, ByVal enWork As Entity.WorkEntity, ByVal enUser As Entity.UserEntiity)
End Sub
End Class
UserNameIsExist类
''' <summary>
''' 判断用户名是否存在
''' </summary>
Public Class UserNameIsExist
Inherits BLL.LogState
''' <summary>
''' 登录状态 判断用户名是否存在
''' </summary>
''' <param name="login">登录</param>
''' <param name="enWork">工作实体</param>
''' <param name="enUser">用户实体</param>
Public Overrides Sub onLog(ByVal login As LoginBLL, ByVal enWork As Entity.WorkEntity, ByVal enUser As Entity.UserEntiity)
Dim factory As DFactory.DataAccess = New DFactory.DataAccess '定义并实例化工厂
Dim IUser As IDAL.IUser '定义接口
IUser = factory.GetUser() '调用工厂方法创建接口
Dim BTable As New DataTable '定义变量datatable
BTable = IUser.IUserIsExit(enUser) '调用接口方法查询用户名是否存在
'判断用户名是否存在即表中是否含有所要查找的数据
If BTable.Rows.Count = 0 Then
Throw New Exception("该用户名不存在") '抛出异常
Else
login.SetState(New PwdIsRight) '调用下一个状态
login.Login(enWork, enUser) '调用loginBLL中的登陆方法
End If
End Sub
End Class
4.对状态模式的理解
刚开始看状态模式特别晕,LoginBLL和LogState子类中间互相地调来调去的,搞不明白它具体是怎么实现各种状态之间的跳转。找了一些资料研究,也和同学交流了一下。现在做一个总结:在登录的地方使用该模式,首先明白它的UML图使用在B层,U层中需要实例化LoginBLL这个类,并调用它的方法Login()即可,返回值为boolean.在B层中,LoginBLL的功能就是处理LogState。Sub New()函数是它的构造函数,实例化时自动将UserNameIsExist这个状态赋给current变量,决定每次登陆时都是从UserNameIsExist这个状态开始进行判断。而SetState这个函数不是给U层使用,而是给登陆状态的各个子类使用的,实现跳转状态。这样的结果就是状态的子类中要调用LoginBLL中SetState函数,而LoginBLL中的Login函数需要调用状态子类中的onLog函数,形成互相调用。当你搞明白了再去看它觉得它还是挺容易理解的。不要一下扎进代码里,多想想那些函数都是干嘛的,在什么时候使用就好了。