ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 一、装饰模式概述 装饰模式的用途,顾名思义,现实生活中我们需要一些装饰品来装饰人,或者物。淡然没有这些装饰,物体和人依然是存在的,这就意味着装饰品并非必须的,我们有时需要一个(项链),或许有时需要二个(项链,耳钉),再或者需要更多(项链,耳钉,戒指……),用一句话概括:装饰模式就是**动态地给一个对象添加一些额外的职责**。 关于更多装饰模式理论:详见博客:[装饰模式——结构型设计模式之四](http://blog.csdn.net/wangyongxia921/article/details/8480229) ## 二、用户装饰模式来装饰机房收费系统登陆 任何一个系统登陆都需要经过验证,这里以机房收费系统为例进行说明。 首先登陆到一个系统,为了系统安全性,我们应该从用户名,密码,来考虑。 登陆系统时需要提供匹配的用户名和密码,然后通过系统的验证通过后,方可登陆成功。 先要验证用户名,是否存在,然后验证用户密码是否正确,如果有登陆状态,最后验证登陆状态是否可以登陆。 在这里,我们可以把用户名,密码,登陆状态看成四对“登陆这个对象”的装饰,使用装饰模式。 先看装饰模式的类图: ![](https://box.kancloud.cn/2016-02-18_56c5ce724b74f.png) 然后结合登陆使用的装饰模式图如下: ![](https://box.kancloud.cn/2016-02-18_56c5ce753a2e1.jpg) 这里省略掉了接口:component。因为这里的concreteComponent只有“login ”,所以没有必要在定义一个接口。我们让TestUser 继承Login 类,其实,TestUser ,也不可以不继承Login ,这样,“Login ”和TestUser 之间就是关联关系,也可以实现。 具体代码实现: Login类的如下:定义了一个抽象方法 ~~~ Public MustInherit Class Login ''' <summary> ''' 检测用户是否可以登陆 ''' </summary> ''' <param name="useren">用户类</param> Public MustOverride Function TestLogin(ByVal useren As UserEntity) As Boolean End Class ~~~ TestUser 类如下; ~~~ ''' <summary> ''' 检测用户类_继承自login 类 ''' </summary> Public MustInherit Class TestUser Inherits Login Public declogin As Login ''' <summary> ''' 设定要装饰的对象 ''' </summary> ''' <param name="declogin"></param> ''' <remarks></remarks> Public Sub SetObject(ByVal declogin As Login) Me.declogin = declogin End Sub ''' <summary> ''' 检测用户是否可以登陆 ''' </summary> ''' <param name="useren">用户类</param> Public Overrides Function TestLogin(ByVal useren As UserEntity) As Boolean '定义返回值 Dim flag As Boolean = False '如果要装饰的对象不为空,就调用装饰方法 If Not (declogin Is Nothing) Then flag = declogin.TestLogin(useren) End If Return flag End Function End Class ' TestUser ~~~ 三个装饰类: ~~~ ''' <summary> ''' 判断用户是否存在 ''' </summary> Public Class UserExist Inherits BLL.TestUser ''' <summary> ''' 检测用户是否可以登陆_用户是否存在 ''' </summary> ''' <param name="useren">用户类</param> Public Overrides Function TestLogin(ByVal useren As UserEntity) As Boolean '定义返回值 Dim flag As Boolean = False Dim af As AbstractFactory.AbstractFactory = AbstractFactory.AbstractFactory.GetInstance() Dim iuser As IDAL.IUser '创建接口库 iuser = af.CreateUser() If Not (iuser.QueryUserInfo(useren) Is Nothing) Then flag = True Else Throw New Exception("用户名不存在,请检查用户名,重新登陆。") End If Return flag End Function End Class ' UserExist ~~~ ~~~ ''' <summary> ''' 验证密码是否正确 ''' </summary> Public Class TestPwd Inherits BLL.TestUser ''' <summary> ''' 检测用户是否可以登陆_检测密码 ''' </summary> ''' <param name="useren">用户类</param> Public Overrides Function TestLogin(ByVal useren As UserEntity) As Boolean '定义返回值 Dim flag As Boolean = False Dim af As AbstractFactory.AbstractFactory = AbstractFactory.AbstractFactory.GetInstance() Dim iuser As IDAL.IUser '创建接口库 iuser = af.CreateUser() If iuser.QueryUserInfo(useren).P_password = useren.P_password Then flag = True Else Throw New Exception("登陆密码不正确,请重新输入。") End If Return flag End Function End Class ' TestPwd ~~~ ~~~ ''' <summary> ''' 查询用户状态 ''' </summary> Public Class UserState Inherits TestUser ''' <summary> ''' 检测用户是否可以登陆——查询用户状态 ''' </summary> ''' <param name="useren">用户类</param> Public Overrides Function TestLogin(ByVal useren As UserEntity) As Boolean '定义返回值 Dim flag As Boolean = False Dim af As AbstractFactory.AbstractFactory = AbstractFactory.AbstractFactory.GetInstance() Dim iuser As IDAL.IUser '创建接口库 iuser = af.CreateUser() If iuser.QueryUserInfo(useren).P_userstatus = "离线" Then flag = True Else Throw New Exception("用户已经在线,不可以重复登陆。") End If Return flag End Function End Class ' UserState ~~~ 主要的类都写完了,接下来就是客户端的调用了, 在调用是,根据装饰模式的特性,我们需要循环嵌套调用,为了使装饰的东西先后顺序稳定, ~~~ ''' <summary> ''' 用户登陆系统方法 ''' </summary> ''' <param name="useren">要登陆的用户实体</param> Public Function Login(ByVal useren As UserEntity, worklogen As WorkLogEntity) As Boolean Dim flag As Boolean = False '判断用户是否存在 Dim Bqueryuser As New BLL.QueryUser '定义登陆变量,存放用户登陆的几种情况 'Dim intLogin As Int32 'intLogin = Bqueryuser.UserInfo(useren) '判断登陆的情况 '**************?????考虑使用迭代器模式 '使用装饰模式 '定义B层装饰模式对象 Dim Blogin As BLL.Login '装饰对象声明 Dim BuserState As New BLL.UserState() Dim BtestPWD As New BLL.TestPwd() Dim BuserExist As New BLL.UserExist() 'Dim BtestUser As BLL.TestUser '装饰过程 '4/声明验证对象 BuserState.SetObject(Blogin) '3状态验证 BtestPWD.SetObject(BuserState) '2密码验证 BuserExist.SetObject(BtestPWD) '1验证用户是否存在 '验证全部通过,然后修改用户状态和插入工作记录 If BuserExist.TestLogin(useren) Then '调用B层方法 If Buser.UpdateUserState(useren) Then '声明工作记录对象 Dim Bworklog As New BLL.WorkLog '调用B层方法 If Bworklog.AddWorkLog(worklogen) Then '插入记录成功返回真 flag = True Throw New Exception("用户登陆成功,马上跳转到主界面!") End If End If End If Return flag End Function ~~~ 通过以上的叙述,装饰模式就结束了。 如果用户需求发生变化,你需要增加价差,或者减少检查,只需要增加/去掉相应类即可,然后再客户端中修改调用对象即可。