## 一、裝飾模式概述
裝飾模式的用途,顧名思義,現實生活中我們需要一些裝飾品來裝飾人,或者物。淡然沒有這些裝飾,物體和人依然是存在的,這就意味著裝飾品并非必須的,我們有時需要一個(項鏈),或許有時需要二個(項鏈,耳釘),再或者需要更多(項鏈,耳釘,戒指……),用一句話概括:裝飾模式就是**動態地給一個對象添加一些額外的職責**。
關于更多裝飾模式理論:詳見博客:[裝飾模式——結構型設計模式之四](http://blog.csdn.net/wangyongxia921/article/details/8480229)
## 二、用戶裝飾模式來裝飾機房收費系統登陸
任何一個系統登陸都需要經過驗證,這里以機房收費系統為例進行說明。
首先登陸到一個系統,為了系統安全性,我們應該從用戶名,密碼,來考慮。
登陸系統時需要提供匹配的用戶名和密碼,然后通過系統的驗證通過后,方可登陸成功。
先要驗證用戶名,是否存在,然后驗證用戶密碼是否正確,如果有登陸狀態,最后驗證登陸狀態是否可以登陸。
在這里,我們可以把用戶名,密碼,登陸狀態看成四對“登陸這個對象”的裝飾,使用裝飾模式。
先看裝飾模式的類圖:

然后結合登陸使用的裝飾模式圖如下:

這里省略掉了接口: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
~~~
通過以上的敘述,裝飾模式就結束了。
如果用戶需求發生變化,你需要增加價差,或者減少檢查,只需要增加/去掉相應類即可,然后再客戶端中修改調用對象即可。
- 前言
- 抽象工廠——創建型設計模式一
- 工廠三姐妹——創建型設計模式之二
- 初識面向對象設計模式
- 建造者模式——創建型模式之三
- 原型模式——創建型設計模式四
- 適配器 and 組合模式——結構性模式之一
- 橋接模式——結構性設計模式之二
- 組合模式——結構型設計模式之三
- 裝飾模式——結構型設計模式之四
- 外觀模式——結構型設計模式之五
- 代理模式——結構型設計模式之六
- 觀察者模式——行為型設計模式之五
- 模板設計——行為設計模式之一
- 命令模式——行為設計模式之二
- 狀態模式——行為型設計模式之三
- 職責模式——行為設計模式之四
- 中介模式——行為模式之六
- 策略+簡單工廠 實戰篇
- 看觀察者怎么全方位觀察機房收費系統
- 登陸也需要裝飾——機房收費系統裝飾模式實戰
- 何為抽象?你有本末倒置嗎?
- 再回首,策略、簡單工廠是否依然?
- 再回首——行為型設計模式