C# 原型模式(C#中的克隆)
C#中的克隆
克隆(Clone)一个类实例(完全拷贝)的思想不是C#的固有属性,但也没有什么理由可以阻
止你自己完成这样的操作。克隆方法出现在C#中的惟一地方是在ADO Dataset处理里。读者可以
创建一个DataSet作为数据库查询的结果,其行指针可以一次移动一行。如果出于某种原因,需要
把索引保持在DataSet的两个位置上,就需要两个“当前行”。C#处理这种情况的最简单方法是克
隆DataSet。
DataSet cloneSet;
cloneSet=myDataSet.Clone();
这种方法并不产生数据的两个拷贝,它只生成两套行指针,用于在记录之间相互独立地移动。
因为实际上只有一个数据表,所以,DataSet的一个克隆体中的任何改变,都会立即反映到另一个
克隆体中。我们在下面的例子中会讨论一个与此类似的问题。
使用原型
我们接下来编写一个简单的程序,从数据库读人数据,然后克隆结果对象。在这个例子中,与
前面的论述一样,原始数据是从一个大数据库中导出来的,而我们只是从一个文件读人数据。文件
具有如下格式:
Kristen Frost, 9, CAT, 26.31, F
Kimberly Watcke, 10, CDEV, 27.37, F
Jaclyn Carey, 10, ARAC, 27.53, F
Megan Crapster, 10, IEHY, 27.68, F
这里要用到先前开发的csFiIe类。首先,创建一个Swimmer类,它包含一个运动员的名字、
俱乐部名字、性别和时间(即成绩),使用第4章开发的csFile类和StringTokenizer类读入这些
数据。
public class Swimmer
{private string name;private string lname,frname;private int age;private string club;private float time;private bool female;public Swimmer(string line){StringTokenizer tok=new StringTokenizer(line,",");spliteName(tok);age=Convert.ToInt32(tok.nextToken());club=tok.nextToken();time=Convert.ToSingle(tok.nextToken());string sx=tok.nextToken().ToUpper();female=sx.Equals("F");}private void spliteName(StringTokenizer tck){name=tok.nextToken();int i=name.IndexOf(" ");if(i>0){frname=name.Substring(0,i);lname=name.Substring(i+1).Trim();}}public bool isFemale(){return female;}public int getAge(){return age;}public float getTime(){return time;}public string getName(){return name;}public string getClun(){return club;}
}
接下来创建一个SwimData类,它包含一个从数据库读人的swimmer对象的ArrayList。
public class SwimData
{protected ArrayList swdata;private int index;public SwimData(){swdata=new ArrayList();}public SwimData(ArrayList swd){swdata=swd;index=0;}public SwimData(string filename){swdata=new ArrayList();csFile f1=new csFile(filename);fl.openForRead();string s=fl.readLine();while(s!=null){Swimmmer sw=new Swimmmer();swdata.Add(sw);s=fl.readLine();}fl.close();}public void moveFirst(){index=0;}public bool hasMoreElements(){return(index<swdata.Count-1);}public void sort(){}public Swimmmer getSwimmer(){if(index<swdata.Count)return (Swimmmer)swdata[index++];else return null;}
}
然后,就可以使用该类读人选手数据,并把它们显示在列表框中。
private void init()
{swdata=new SwimData("swimmers.txt");reload();
}private void reload()
{lsKids.Items.Clear();swdata.moveFirst();while(swdata.hasMoreElements()){Swimmer sw=swdata.getSwimmer();lsKids.Items.Add(sw.getName());}
}
单击“一>”按钮,克隆Swata类,并在新类中对数据进行不同的排序。因为创建一个新的
类实例会比较慢,而且我们想以两种形式保存数据,所以也对数据进行了克隆。
private void btClone_Click(object sender,EventArgs e)
{SwimData newSd=(SwimData)swdata.Clone();newSd.Sort();while(newSd.hasMoreElements()){Swimmer sw=(Swimmer)newSd.getSwimmer();lsNewKids.Items.Add(sw.getName());}
}