您的位置:首页 > 其它

用实例解说Dot Net设计模式——装饰模式

2005-12-24 13:45 423 查看
1.装饰模式的概述
2.1 什么是装饰模式
在不改变对象的前提下,动态增加其功能,即我们不希望改变原有的类,或采用创建子类的方法增加功能,这种情况下需要采用装饰模式。

2.2结构
修饰一个对象后,其接口不应该发生变化;否则这个对象不能被原有调用者使用,修饰失去了意义。由此引出了装饰模式结构最重要的一点,即装饰者和被装饰者具有相同的接口。换句话说,动态增加的功能不应该破坏已有的接口。
装饰模式的结构如下图所示。
Public Class Decorator
2 Inherits System.Web.UI.UserControl
3 Private _Control As String
4 Private _ContentPane As Web.UI.Control
5 Public Property Control() As String
6 Get
7 Return _Control
8 End Get
9 Set(ByVal Value As String)
10 _Control = Value
11 End Set
12 End Property
13 Public Property ContentPane() As Web.UI.Control
14 Get
15 Return _ContentPane
16 End Get
17 Set(ByVal Value As Web.UI.Control)
18 _ContentPane = Value
19 End Set
20 End Property
21
22 Public Sub AddControl(ByVal c As UserControl)
23 _ContentPane.Controls.Add(c)
24 End Sub
25End Class
26首先需要注意Decorator必须与被装饰者具有相同的接口,因此它是UserControl的子类。在Decorator中定义了装载被装饰者的方法AddControl,和装载被装饰者的容器ContentPane。
在具体的装饰者中,后台的可执行代码很少,主要定义装饰界面,在SubDecorator中定义了带有图形边框的界面:

1Public Class SubDecorator
2 Inherits Decorator
3 <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
4
5 End Sub
6 Protected WithEvents cp As System.Web.UI.HtmlControls.HtmlTableCell
7 Private designerPlaceholderDeclaration As System.Object
8 Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
9 InitializeComponent()
10 Me.ContentPane = Me.cp
11 End Sub
12 Public Sub Page_load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
13 If Me.Control <> "" Then
14 Dim c As UserControl = LoadControl(Me.Control)
15 Me.AddControl(c)
16 End If
17 End Sub
18End Class
在另一个装饰器中如下定义了可以使被装饰者滚动显示的SubDecoratorB.

Public Class SubDecoratorB
Inherits Decorator

Protected WithEvents Top As System.Web.UI.WebControls.Literal
Protected WithEvents Buttom As System.Web.UI.WebControls.Literal
Protected WithEvents cp As System.Web.UI.WebControls.Panel

#Region " Web 窗体设计器生成的代码 "

'该调用是 Web 窗体设计器所必需的。
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

End Sub

'注意: 以下占位符声明是 Web 窗体设计器所必需的。
'不要删除或移动它。
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: 此方法调用是 Web 窗体设计器所必需的
'不要使用代码编辑器修改它。
InitializeComponent()
Me.ContentPane = Me.cp
End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'在此处放置初始化页的用户代码
If Me.Control <> "" Then
Dim c As UserControl = LoadControl(Me.Control)
Me.AddControl(c)
Me.Top.Text = ShowRollBegin("100")
Me.Buttom.Text = ShowRollEnd()

End If
End Sub

Private Function ShowRollBegin(ByVal strDisplayHeight) As String
Return "<marquee style='bottom:0px;height:'" & strDisplayHeight & "px;top:0px' id='News' scrollamount=1 scrolldelay=10 behavior='scroll' direction='up' onmouseover='this.stop()' onmouseout='this.start()'>"
End Function

Private Function ShowRollEnd() As String
Return "</marquee>"
End Function
End Class

我们定义一个很简单的HelloWorld用户组件用来测试,这个组件没有后台代码,仅仅有一个Lable组件:
<asp:Label Runat="server" id="Label2">HelloWorld</asp:Label>
我们用上面的两个装饰器装饰这个组件:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'在此处放置初始化页的用户代码
Dim c As Decorator = LoadControl("SubDecorator.ascx")
Dim d As Decorator = LoadControl("SubDecoratorB.ascx")
d.Control = "HelloWorld.ascx"
Me.Controls.Add(c)
c.AddControl(d)
End Sub

感兴趣的朋友可以做一个例子看看效果,别看上面一大堆代码,其实仔细观察不难看出实际上是几个UserControl的相互套用来实现装饰模式的。

3.我们在看一个.NET中的装饰模式实例
BufferedStream是经典的装饰模式,GOF在《设计模式》中已有介绍。并且在多种语言平台上都有相同的实现,在.NET中也不例外。
BufferedStream的作用是为另一流上的读写操作添加一个缓冲层,缓冲区是内存中的字节块,用于缓存数据。从而减少对操作系统的调用次数,缓冲区可提高读取和写入性能。
Stream是流的基类,抽象了对流的操作。根据流的来源和性质的不同,Stream的子类有System.Data.OracleClient.OracleBFile,System.Data.OracleClient.OracleLob,System.
IO.BufferedStream,System.IO.FileStream,System.IO.MemoryStream,System.Net.Sockets.NetworkStream和System.Security.Cryptography.CryptoStream。
如FileStream可以打开一个文件并以流的方式读写文件,MemoryStream读写内存中的数据流,而NetworkStream则操作Scokets连接的TCP流。其中,BufferedStream非常特殊,它不直接创建英雄模范种类型的流,而是在已有流上执行附加的操作。由于它继承了Stream,因此使用上与一般的流没有不同,只是为现有的流增加了缓冲功能。
通过采用装饰模式,BufferedStream使Stream具有了缓存功能而不用改动接口。这就是装饰模式所要达到的效果。这里就不再举具体的例子了,其实很简单,朋友可以自己试着写一下.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: