争怎路由网:是一个主要分享无线路由器安装设置经验的网站,汇总WiFi常见问题的解决方法。

C#与.NET中的原型克隆[zt]

时间:2024/7/13作者:未知来源:争怎路由网人气:

发表日期: 17/04/2002 18:51:10
发表人: Ashish Jaiman
发表人信箱: Ashish.Jaiman@lexign.com
发表人网址: http://www.lexign.com

与其不断地创建类实例,有时反不如使用原型克隆方法,拷贝已有的实例,然后适当地作些改动。当使用的子类仅仅在对象类型上不同于父类,也可以用原型克隆方法来减少子类数量。

===========================================================
创建类的实例是相当花费时间而且比较复杂的事,与其不断地创建类实例,有时反不如使用原型克隆方法,拷贝已有的实例,然后适当地作些改动。当使用的子类仅仅在对象类型上不同于父类,也可以用原型克隆方法来减少子类数量。
原型设计模式的重点在于“用克隆的方式创建对象”。有时为了得到不同的对象类型而创建不同子类,这时用原型设计就只需要创建一个子类(在这个子类里有指向基类的引用),然后创建这个子类的对象。以后就只要创建这个子类的对象就能用了。每个对象都是能被克隆的,使用原型克隆将大大减少子类的数量。

用系统的ICloneable命名可以实现克隆。ICloneable的唯一成员就是Clone方法,它将返回一个新的类实例,并包含与科隆对象同样的参数值。

ICloneable.Clone 方法的描述:
[Visual Basic] Function Clone() As Object
[C#] object Clone();

必需指出的是,Clone()方法是一种“浅”拷贝,它只返回指向原型的引用。另外还有一种“深”拷贝,它拷贝整个实例对象。用ISerializable接口可以实现对象的深拷贝。

克隆对象的任何变化都将影响到原型,反之亦然。克隆方法的另外一个不足之处在于它的子类都必需使用Clone()方法,很难使用其他的拷贝方法。

在示范例子里(文末可以下载),我创建了一个EmpData类,它有ICloneable和ISerializable二种接口。ICloneable用于创建“浅”拷贝,ISerializable用于创建“深”拷贝。前者仅拷贝对象的引用,后者则拷贝整个对象。EmpData类有二个方法:GetEmpData和ChangeEmpData。前者将源对象克隆成为一个字符串,后者则可以对其进行修改。

二种方法都可以被使用,并用于验证深浅克隆方法的不同。浅克隆对象的变化将影响到被克隆的原型对象,而深克隆对象的变化则不改变原型对象数据。

EmpData的构造函数是挺花时间的,因为它要读取XML文件并创建对象。

XML文件:
<employees>
<employee>
<firstname>ashish</firstname>
<lastname>jaiman</lastname>
</employee>
<employee>
<firstname>jaya</firstname>
<lastname>pandey</lastname>
</employee>
<employee>
<firstname>neeraj</firstname>
<lastname>jaiman</lastname>
</employee>
<employee>
<firstname>ashutosh</firstname>
<lastname>sharma</lastname>
</employee>
<employee>
<firstname>zerman</firstname>
<lastname>billingslea</lastname>
</employee>
<employee>
<firstname>bernd</firstname>
<lastname>burkhardt</lastname>
</employee>
<employee>
<firstname>sanjeev</firstname>
<lastname>bhutt</lastname>
</employee>
<employee>
<firstname>li</firstname>
<lastname>li</lastname>
</employee>
</employees>

C#执行程序:
using System;
using System.Xml;
using System.IO;
using System.Collections;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
 [Serializable()]
 public class CEmpData: ICloneable,ISerializable {
 private ArrayList ArrEmp;
 public CEmpData(){
  ArrEmp = new ArrayList();
  InitializeData();
  }
 private void InitializeData(){
  XmlDocument xmlDoc = new XmlDocument();
  CEmp objEmp;
  xmlDoc.Load("empdata.xml");
  foreach(XmlNode node in xmlDoc.DocumentElement.ChildNodes){
   objEmp = new CEmp();
   objEmp.FName = node.SelectSingleNode("firstname").InnerText;
   objEmp.LName = node.SelectSingleNode("lastname").InnerText; 
   ArrEmp.Add (objEmp); 
   }
  }
 public CEmpData(SerializationInfo info,StreamingContext context){
  int intCount=0;
  CEmp objEmp;
  ArrEmp = new ArrayList();
  intCount = (int)info.GetValue("emp_count", intCount.GetType());
  for (int intIndex = 0;intIndex<intCount;intIndex++){
   objEmp = new CEmp(info,context,intIndex);
   ArrEmp.Add(objEmp);
   }
  }
 public void GetObjectData(SerializationInfo info,StreamingContext context){
  CEmp objEmp;
  info.AddValue("emp_count", ArrEmp.Count);
  for (int intIndex = 0;intIndex<ArrEmp.Count ;intIndex++) {
   objEmp = (CEmp)ArrEmp[intIndex];
   objEmp.GetObjectData(info,context,intIndex); 
   }
  }
 public object Clone(){
  return this;
  }
 public object Clone(bool Deep){
  if(Deep) 
   return CreateDeepCopy();
  else
   return Clone();
  }
 private CEmpData CreateDeepCopy(){
  CEmpData objEmpCopy;
  Stream objStream;
  BinaryFormatter objBinFormatter = new BinaryFormatter();
  try{
   objStream = File.Open("Empdata.bin", FileMode.Create);
   objBinFormatter.Serialize(objStream, this);
   objStream.Close();
   objStream = File.Open("Empdata.bin", FileMode.Open);
   objEmpCopy = (CEmpData)objBinFormatter.Deserialize(objStream);
   objStream.Close();
   return objEmpCopy;
   }
  catch(Exception ex){
   Console.WriteLine (ex.ToString());
   return null;
   }
  }
 public string GetEmpData(){
  string strEmpData="";
  for (int intCount = 0;intCount < ArrEmp.Count;intCount++){
   strEmpData = strEmpData + ((CEmp)ArrEmp[intCount]).FName + "\t" + ((CEmp)ArrEmp[intCount]).LName+ "\n";
   }
  return strEmpData;
  }
 public void ChangeEmpData(){
  foreach (CEmp objEmp in ArrEmp){
   objEmp.FName ="FirstName";
   objEmp.LName ="LastName";
   }
  }
 }
using System;
using System.Runtime.Serialization;
public class CEmp {
 private string mstrFName;
 private string mstrLName;
 public string FName{
  get{return mstrFName;}
  set{mstrFName = value;}
 }
 public string LName{
  get{return mstrLName;}
  set{mstrLName = value;}
  }
 public CEmp(){}
 public CEmp(SerializationInfo info, StreamingContext context, int intIndex){
  string temp = "temp";
  mstrFName = (string)info.GetValue("emp_fname" + intIndex,temp.GetType());
  mstrLName = (string)info.GetValue("emp_lname" + intIndex, temp.GetType());
  }
 public void GetObjectData(SerializationInfo info, StreamingContext context, int intIndex){
  info.AddValue("emp_fname" + intIndex, mstrFName);
  info.AddValue("emp_lname" + intIndex, mstrLName);
  }
 }


VB.NET 执行程序:
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

引入System.Runtime.Serialization:
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

本文附件:http://www.chinaOk.net/down/prototype.zip

关键词:C#与.NET中的原型克隆[zt]




Copyright © 2012-2018 争怎路由网(http://www.zhengzen.com) .All Rights Reserved 网站地图 友情链接

免责声明:本站资源均来自互联网收集 如有侵犯到您利益的地方请及时联系管理删除,敬请见谅!

QQ:1006262270   邮箱:kfyvi376850063@126.com   手机版