** 实现 ** ** Prototype ** ** 设计模式 ** ** **
** Implementing the Prototype design Pattern **
当我建立一个类的实例很复杂时,我们可以使用 Prototype 模式。与其建立很多类的实例,还不如进行适当的修改后,使用最初的实例的副本。使用 ** Prototype ** ** 模式 ** ,可以通过克隆一个原型,减少子类的数量。 Prototype 模式可以减少类的实例的数量。
在这个模式中,通过克隆来创建对象。我们有时创建很多的子类,除了通过很多的子类来创建不同的对象,我们还可以只需要唯一的一个子类,这个子类保持对每个对象基类的引用,并通过这个子类创建对象。通过向子类的构造函数传递参数并克隆对象。每个对象都实现 clone 方法,所以可以被克隆。我们可以使用 ** Prototype ** ** 模式,通过克隆 ** 原型 ** 来减少子类的数量。 ** ** **
** ** ** 克隆可以通过实现 ** Icloneable 接口来实现。 Icloneable 接口中唯一的方法是 Clone ,并返回一个新的类的实例。
** ICloneable.Clone method signature
** [VisualBasic] **_Function Clone() As Object
_ ** [C#] **_object Clone();
_ **
**_
_ ** 我们必须了解 Clone() 方法只是一种浅表复制( Shallow copy ),而不是深层复制( Deep copy )。所以它只是返回一个引用,而不象深层复制( Deep copy )那样创建一个复制的实例。我们可以通过使用 Iserializable 接口来实现深层复制( Deep copy )。
另一个缺点就是原型的每个子类必须实现 Clone() 方法,有时候,增加 clone 方法是很困难的。
在这个例子中,我建立了 EmpData 类,并且实现了 Icloneable 接口和 Iserializable 接口。 Icloneable 接口需要实现 Clone 方法,使得类可以被复制。 Iserializable 接口为了实现对 EmpData 类的深层复制( Deep copy )。使用的方法为:将 EmpData 对象序列化为一个文件,也可以将这个文件反序列化为一个 EmpData 对象。
EmpData 类包含两个方法: GetEmpData 和 ChangeEmpData 。这两个方法被用来以一个字符串( string )的形式获取 EmpData 对象、更改 EmpData 类。每个方法都可以被调用,来检验浅表复制( Shallow copy )和深层复制( Deep copy )的不同。浅表复制( Shallow copy )时,如果 EmpData 类改变时,这个变化也会同时出现在 EmpData 的克隆对象中;而在深层复制( Deep copy ),如果 EmpData 对象发生改变时,这个变化不会出现在 EmpData 的克隆对象中。
EmpData 类的构造函数读取 XML 文件并创建 Emp 对象。
** XML ** ** 文件 ** ** **

** VB.Net ** ** 实现 ** ** **
Imports System.Xml
Imports System.IO
Imports System.Collections
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
1<serializable()> Public Class CEmpData
2
3Implements ICloneable, ISerializable
4
5Private ArrEmp As ArrayList
6
7Public Sub New ()
8
9Dim xmldoc As New XmlDocument
10
11Dim node As XmlNode
12
13Dim objEmp As CEmp
14
15ArrEmp = New ArrayList
16
17xmldoc.Load("empdata.xml")
18
19For Each node In xmldoc.DocumentElement.ChildNodes
20
21objEmp = New CEmp
22
23objEmp.FName = node.SelectSingleNode("firstname").InnerText
24
25objEmp.LName = node.SelectSingleNode("lastname").InnerText
26
27ArrEmp.Add(objEmp)
28
29Next
30
31End Sub
32
33Public Sub New ( ByVal info As SerializationInfo, ByVal context As StreamingContext)
34
35Dim intIndex As Integer
36
37Dim intCount As Integer
38
39Dim objEmp As CEmp
40
41ArrEmp = New ArrayList
42
43intCount = CInt (info.GetValue("emp_count", GetType ( String )))
44
45For intIndex = 0 To intCount - 1
46
47objEmp = New CEmp(info, context, intIndex)
48
49ArrEmp.Add(objEmp)
50
51Next
52
53End Sub
54
55Public Function Clone() As Object Implements ICloneable.Clone
56
57Try
58
59Return Me
60
61Catch ex As Exception
62
63MsgBox(ex.ToString)
64
65End Try
66
67End Function
68
69Public Function Clone( ByVal Deep As Boolean ) As Object
70
71Try
72
73If Deep Then
74
75Return CreateDeepCopy()
76
77Else
78
79Return Clone()
80
81End If
82
83Catch ex As Exception
84
85MsgBox(ex.ToString)
86
87End Try
88
89End Function
90
91Private Function CreateDeepCopy() As CEmpData
92
93Dim objEmpCopy As CEmpData
94
95Dim objStream As Stream
96
97Dim objBinFormatter As New BinaryFormatter
98
99Try
100
101objStream = File.Open("Empdata.bin", FileMode.Create)
102
103objBinFormatter.Serialize(objStream, Me )
104
105objStream.Close()
106
107objStream = File.Open("Empdata.bin", FileMode.Open)
108
109objEmpCopy = CType (objBinFormatter.Deserialize(objStream), CEmpData)
110
111objStream.Close()
112
113CreateDeepCopy = objEmpCopy
114
115Catch ex As Exception
116
117MsgBox(ex.ToString)
118
119End Try
120
121End Function
122
123Public Sub GetObjectData( ByVal info As System.Runtime.Serialization.SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext) Implements System.Runtime.Serialization.ISerializable.GetObjectData
124
125Dim intIndex As Integer
126
127Dim objEmp As CEmp
128
129info.AddValue("emp_count", ArrEmp.Count)
130
131For intIndex = 0 To ArrEmp.Count - 1
132
133objEmp = ArrEmp(intIndex)
134
135objEmp.GetObjectData(info, context, intIndex)
136
137Next
138
139End Sub
140
141Public Function GetEmpData() As String
142
143Dim intCount As Integer
144
145Dim strEmpData As String
146
147For intCount = 0 To ArrEmp.Count - 1
148
149strEmpData = strEmpData & CType (ArrEmp(intCount), CEmp).FName & Chr(9) & CType (ArrEmp(intCount), CEmp).LName & Chr(13)
150
151Next
152
153GetEmpData = strEmpData
154
155End Function
156
157Public Sub ChangeEmpData()
158
159Dim objEmp As CEmp
160
161For Each objEmp In ArrEmp
162
163objEmp.FName = "FirstName"
164
165objEmp.LName = "LastName"
166
167Next
168
169End Sub
170
171End Class
172
173Public Class CEmp
174
175Private mstrFName As String
176
177Private mstrLName As String
178
179Public Property FName() As String
180
181Get
182
183FName = mstrFName
184
185End Get
186
187Set ( ByVal Value As String )
188
189mstrFName = Value
190
191End Set
192
193End Property
194
195Public Property LName() As String
196
197Get
198
199LName = mstrLName
200
201End Get
202
203Set ( ByVal Value As String )
204
205mstrLName = Value
206
207End Set
208
209End Property
210
211Public Sub New ()
212
213End Sub
214
215<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-l
216---</serializable()>