完成Prototype設(shè)計(jì)模式
發(fā)表時(shí)間:2023-07-27 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]實(shí)現(xiàn)Prototype設(shè)計(jì)模式Implementing the Prototype design Pattern 當(dāng)我建立一個(gè)類的實(shí)例很復(fù)雜時(shí),我們可以使用Prototype模式。與其建立很多類的實(shí)...
實(shí)現(xiàn)Prototype設(shè)計(jì)模式
Implementing the Prototype design Pattern
當(dāng)我建立一個(gè)類的實(shí)例很復(fù)雜時(shí),我們可以使用Prototype模式。與其建立很多類的實(shí)例,還不如進(jìn)行適當(dāng)?shù)男薷暮,使用最初的?shí)例的副本。使用Prototype模式,可以通過克隆一個(gè)原型,減少子類的數(shù)量。Prototype模式可以減少類的實(shí)例的數(shù)量。
在這個(gè)模式中,通過克隆來創(chuàng)建對象。我們有時(shí)創(chuàng)建很多的子類,除了通過很多的子類來創(chuàng)建不同的對象,我們還可以只需要唯一的一個(gè)子類,這個(gè)子類保持對每個(gè)對象基類的引用,并通過這個(gè)子類創(chuàng)建對象。通過向子類的構(gòu)造函數(shù)傳遞參數(shù)并克隆對象。每個(gè)對象都實(shí)現(xiàn)clone方法,所以可以被克隆。我們可以使用Prototype模式,通過克隆原型來減少子類的數(shù)量。
克隆可以通過實(shí)現(xiàn)Icloneable接口來實(shí)現(xiàn)。Icloneable接口中唯一的方法是Clone,并返回一個(gè)新的類的實(shí)例。
ICloneable.Clone method signature
[VisualBasic] Function Clone() As Object
[C#] object Clone();
我們必須了解Clone()方法只是一種淺表復(fù)制(Shallow copy),而不是深層復(fù)制(Deep copy)。所以它只是返回一個(gè)引用,而不象深層復(fù)制(Deep copy)那樣創(chuàng)建一個(gè)復(fù)制的實(shí)例。我們可以通過使用Iserializable接口來實(shí)現(xiàn)深層復(fù)制(Deep copy)。
另一個(gè)缺點(diǎn)就是原型的每個(gè)子類必須實(shí)現(xiàn)Clone()方法,有時(shí)候,增加clone方法是很困難的。
在這個(gè)例子中,我建立了EmpData類,并且實(shí)現(xiàn)了Icloneable接口和Iserializable接口。Icloneable接口需要實(shí)現(xiàn)Clone方法,使得類可以被復(fù)制。Iserializable接口為了實(shí)現(xiàn)對EmpData類的深層復(fù)制(Deep copy)。使用的方法為:將EmpData對象序列化為一個(gè)文件,也可以將這個(gè)文件反序列化為一個(gè)EmpData對象。
EmpData類包含兩個(gè)方法:GetEmpData和ChangeEmpData。這兩個(gè)方法被用來以一個(gè)字符串(string)的形式獲取EmpData對象、更改EmpData類。每個(gè)方法都可以被調(diào)用,來檢驗(yàn)淺表復(fù)制(Shallow copy)和深層復(fù)制(Deep copy)的不同。淺表復(fù)制(Shallow copy)時(shí),如果EmpData類改變時(shí),這個(gè)變化也會(huì)同時(shí)出現(xiàn)在EmpData的克隆對象中;而在深層復(fù)制(Deep copy),如果EmpData對象發(fā)生改變時(shí),這個(gè)變化不會(huì)出現(xiàn)在EmpData的克隆對象中。
EmpData類的構(gòu)造函數(shù)讀取XML文件并創(chuàng)建Emp對象。
XML 文件
VB.Net 實(shí)現(xiàn)
Imports System.Xml
Imports System.IO
Imports System.Collections
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
<Serializable()> Public Class CEmpData
Implements ICloneable, ISerializable
Private ArrEmp As ArrayList
Public Sub New()
Dim xmldoc As New XmlDocument
Dim node As XmlNode
Dim objEmp As CEmp
ArrEmp = New ArrayList
xmldoc.Load("empdata.xml")
For Each node In xmldoc.DocumentElement.ChildNodes
objEmp = New CEmp
objEmp.FName = node.SelectSingleNode("firstname").InnerText
objEmp.LName = node.SelectSingleNode("lastname").InnerText
ArrEmp.Add(objEmp)
Next
End Sub
Public Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
Dim intIndex As Integer
Dim intCount As Integer
Dim objEmp As CEmp
ArrEmp = New ArrayList
intCount = CInt(info.GetValue("emp_count", GetType(String)))
For intIndex = 0 To intCount - 1
objEmp = New CEmp(info, context, intIndex)
ArrEmp.Add(objEmp)
Next
End Sub
Public Function Clone() As Object Implements ICloneable.Clone
Try
Return Me
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Function
Public Function Clone(ByVal Deep As Boolean) As Object
Try
If Deep Then
Return CreateDeepCopy()
Else
Return Clone()
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Function
Private Function CreateDeepCopy() As CEmpData
Dim objEmpCopy As CEmpData
Dim objStream As Stream
Dim objBinFormatter As New BinaryFormatter
Try
objStream = File.Open("Empdata.bin", FileMode.Create)
objBinFormatter.Serialize(objStream, Me)
objStream.Close()
objStream = File.Open("Empdata.bin", FileMode.Open)
objEmpCopy = CType(objBinFormatter.Deserialize(objStream), CEmpData)
objStream.Close()
CreateDeepCopy = objEmpCopy
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Function
Public Sub GetObjectData(ByVal info As System.Runtime.Serialization.SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext) Implements System.Runtime.Serialization.ISerializable.GetObjectData
Dim intIndex As Integer
Dim objEmp As CEmp
info.AddValue("emp_count", ArrEmp.Count)
For intIndex = 0 To ArrEmp.Count - 1
objEmp = ArrEmp(intIndex)
objEmp.GetObjectData(info, context, intIndex)
Next
End Sub
Public Function GetEmpData() As String
Dim intCount As Integer
Dim strEmpData As String
For intCount = 0 To ArrEmp.Count - 1
strEmpData = strEmpData & CType(ArrEmp(intCount), CEmp).FName & Chr(9) & CType(ArrEmp(intCount), CEmp).LName & Chr(13)
Next
GetEmpData = strEmpData
End Function
Public Sub ChangeEmpData()
Dim objEmp As CEmp
For Each objEmp In ArrEmp
objEmp.FName = "FirstName"
objEmp.LName = "LastName"
Next
End Sub
End Class
Public Class CEmp
Private mstrFName As String
Private mstrLName As String
Public Property FName() As String
Get
FName = mstrFName
End Get
Set(ByVal Value As String)
mstrFName = Value
End Set
End Property
Public Property LName() As String
Get
LName = mstrLName
End Get
Set(ByVal Value As String)
mstrLName = Value
End Set
End Property
Public Sub New()
End Sub
Public Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext, ByVal intIndex As Integer)
mstrFName = CStr(info.GetValue("emp_fname" & intIndex, GetType(String)))
mstrLName = CStr(info.GetValue("emp_lname" & intIndex, GetType(String)))
End Sub
Public Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext, ByVal intIndex As Long)
info.AddValue("emp_fname" & intIndex, mstrFName)
info.AddValue("emp_lname" & intIndex, mstrLName)
End Sub
End Class