状态模式的实例学习

上篇博客介绍了策略模式的实例使用,这篇博客介绍一下状态模式的实例使用。

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函数,形成互相调用。当你搞明白了再去看它觉得它还是挺容易理解的。不要一下扎进代码里,多想想那些函数都是干嘛的,在什么时候使用就好了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值