设计模式之C#实现---- ProtoType
该模式的意图是:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。那么首先我们应该已经有了一个对象,同时这个对象还支持自我复制(科隆)。在FCL里面我们知道有一个接口专门用来规定这么一个契约,那就是ICloneable接口,该接口只有一个方法Clone,以下MSDN对该接口中对该接口的方法的说明:创建作为当前实例副本的新对象。Clone 既可作为深层副本实现,也可作为浅表副本实现。在深层副本中,所有的对象都是重复的;而在浅表副本中,只有顶级对象是重复的,并且顶级以下的对象包含引用。结果克隆必须与原始实例具有相同的类型或是原始实例的兼容类型。这样一来如果我们想要一个可以自我复制的对象我们可以申明一个类MyClass该类继承接口ICloneable 。
下面我们举一个显示生活中的例子来说明这种方法是普遍存在的的。我想我们可能都知道细胞,细胞是组成机体的最小单位(也许不是),我们知道任何(也许是部分)动物或者植物都是由一个细胞分裂的来的,所以我们可以理解细胞就是一种带有Clone方法的对象,细胞可以不断的调用该方法是我们的机体趋于完整。还可以举一个例子就是病毒,我们都经历过Sars期间,我想如果Sars没有自我复制的功能它就不可能成气候,还有一个人人都要实现的例子就是钱(我不知道是不是恰当),我们可以通过我们的努力使得1块钱变成2块…当然每个人的实现方法不同自然结果也就不同了(不知道是否贴切)。当然上面所据的前两个例子应该都是一种深层副本,因为他一旦被复制就是一个独立的个体,在内存中就是不同的两个地址,而潜表拷贝则不同,表面上看是两个实际上是一个对象的两个引用,也就是实际上他们存在于同一个地址,如果我们改变其中一个那么另一个也会改变。应此我们可以看出应用这种模式的关键就是如何实现Clone的方法。
下面是PROTOTYPE的结构图(来自ROSE2003):
浅拷贝和深拷贝之间的区别:浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象中引用型字段的值他将反映在原是对象中,也就是说原始对象中对应的字段也会发生变化。深拷贝与浅拷贝不同的是对于引用的处理,深拷贝将会在新对象中创建一个新的和原是对象中对应字段相同(内容相同)的字段,也就是说这个引用和原是对象的引用是不同的,我们在改变新对象中的这个字段的时候是不会影响到原始对象中对应字段的内容。所以对于原型模式也有不同的两种处理方法:对象的浅拷贝和深拷贝。在FCL中的System命名空间下面有一个浅拷贝的方法叫:MemberwiseClone它是创建当前 Object 的浅表副本。在我们的例子里我想实现一个浅拷贝同时在实现一个深拷贝,这样可以加深理解。
下面是一个浅拷贝的例子:
using System;
namespace Prototype_Shallow{
//因为我们在FCL里面已经有这样的接口所以我们就不定义新的Prototype了
public class ConcretePrototype1 : ICloneable{
private int m_ID;
public int ID{
get{
return this.m_ID;
}
}
public ConcretePrototype1(int id){
this.m_ID = id;
}
public object Clone(){
return this.MemberwiseClone();
}
}
public class ConcretePrototype2 : ICloneable{
private int m_ID;
public int ID
{
get
{
return this.m_ID;
}
}
public ConcretePrototype2(int id){
this.m_ID = id;
}
public object Clone(){
return this.MemberwiseClone();
}
}
}
我们具体的原型都继承了接口ICloneable,同时也实现了该接口里面唯一个一个方法Clone。我们可以在客户端这样创建对象ConcretePrototype1 p1 = new ConcretePrototype1(1); ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();首先我们创建了对象p1,接下来我们用通过p1的科隆方法得到了对象c1,这就是一种浅拷贝(因为MemberwiseClone是浅拷贝)。
接下来我们将要实现的是深拷贝,这个一个相对浅拷贝比较困难的工作,我们在拷贝对象的时候不但要拷贝他的数值型字段同时还要复制它的引用字段(有的时候这种工作是非常困难的也许是不可能的)。
namespace Prototype_Deep{
using System.Collections;
public class ConcretePrototype : ICloneable
{
private int m_ID;
public int ID
{
get
{
return this.m_ID;
}
}
private ArrayList m_arrayList = new ArrayList();
public ConcretePrototype(int id)
{
this.m_ID = id;
this.m_arrayList.Add("FirstObject");
this.m_arrayList.Add("SecondObject");
// ...
}
public object Clone()
{
ConcretePrototype c = new ConcretePrototype(this.ID);
c.m_arrayList = new ArrayList();
c.m_arrayList.Add("FirstObject");
c.m_arrayList.Add("SecondObject");
return c;
}
public ConcretePrototype DeepClone(){
return (ConcretePrototype)this.Clone();
}
}
}
该代码显示了如何实现深拷贝,深拷贝的原则就是对于那些引用的字段您需要new(new之前想想是不是能用前面学过的某个创建型的模式实现,这是一个好的习惯)一个出来,然后对该字段里面的对象一一拷贝,这样以来很容易出现循环拷贝,所以说深拷贝要比浅拷贝更难一些。客户端可以通过ConcretePrototype p = new ConcretePrototype(1);ConcretePrototype c = p.DeepClone();来实现克隆一个新的对象。代码如下:
ConcretePrototype p = new ConcretePrototype(1);
ConcretePrototype c = p.DeepClone();
this.richTextBox1.AppendText(p.ToString()+":"+p.ID.ToString()+"/n");
this.richTextBox1.AppendText(c.ToString()+":"+c.ID.ToString()+"/n");
c.m_arrayList[0] = "Changed";
for(int i = 0;i<=1;i++){
this.richTextBox1.AppendText(c.m_arrayList[i].ToString());
}
this.richTextBox1.AppendText("/n");
for(int i = 0;i<=1;i++){
this.richTextBox1.AppendText(p.m_arrayList[i].ToString());
}
这样我们将看到结果我们在改变科隆出来的对象的时候原来的对象是不变的。前面的浅拷贝我们有做这种比较,有兴趣的读者可以试一试,在FCL中大部分的科隆都是浅拷贝,我们可以看看实现ICloneable接口的类,几乎全部都是浅拷贝。顺便说一下在工作流中关于处理(Process)对象以及其他的相关对象我们可以使用这种Clone的方法,这个您可以参看CRM的WorkFlow中的类,又很多都实现了该方法。
希望我的文章可以帮助您很好的理解设计模式中的原型,关于该模式中的详细信息您可以参看GOF的书上面说得很清楚。在这次实现中我们利用了FCL的接口,没有自己写接口但是效果是一样的。如果在文章中出现什么不对的地方忘网友指正:wu_jian830@hotmail.com谢谢您的支持,希望我们可以共同进步。
相关文章:

快速排序(二)最后修改
1 //2012-07-162 void quickSort(element list[], int left, int right)//快速排序3 {4 int ileft;5 int jright;6 7 if(i > j) //判断需要i<j8 return;9 10 element templist[i]; 11 12 while(i<j) 13 { 14 while(i<j …
性能超越GPU、FPGA,华人学者提出软件算法架构加速AI实时化
作者 | 王言治,美国东北大学电子与计算机工程系助理教授出品 | AI科技大本营(ID:rgznai100)近年来,机器学习(Machine Learning)领域的研究和发展可谓是与日俱新,各式各样与机器学习相关的研究成果与应用层出不穷&#…

PHP获取毫秒时间戳,利用microtime()函数
PHP获取毫秒时间戳,利用microtime()函数 php本身没有提供返回毫秒数的函数,但提供了一个microtime()函数,借助此函数,可以很容易定义一个返回毫秒数的函数。php的毫秒是没有默认函数的,但提供了一个microtime()函数&am…

.NET中添加控件数组
作者:cuike519的专栏 http://blog.csdn.net/cuike519/添加控件数组 在.NET里面我好像没有找到有关于控件数组的说明,但是前两天偶在网上看到了一篇关于如何在.NET里面实现控件数组的文章(该文章请参看MSDN).记得大学的时候在使用VB的时候使用过控件数组,可是到了…
如何在机器学习的框架里实现隐私保护?
编者按:数据时代,人们从技术中获取便利的同时,也面临着隐私泄露的风险。微软倡导负责任的人工智能,因此机器学习中的隐私保护问题至关重要。本文介绍了目前机器学习中隐私保护领域的最新研究进展,讨论了机密计算、模型…

函数图像轻松画:教你用永中图象
函数图像轻松画:教你用永中图象 函数图像轻松画:教你用永中图象转载于:https://blog.51cto.com/premium/933220

c语言语系的命名风格和java系命名风格
c语言系的命名风格:单词之间使用下划线分隔。如上图。 java语言是另外一个系,javascript属于java语系(当年就是想借助java的名气所以命名javascript)。java语系是驼峰式命名法,如getElementById()。如果使用c语系命名风格则使用下划线分隔 ge…

全国IP地址分配表
xa.sn.cn,西安公众网,西安,陕西,CN,202.100.0.* xa.sn.cn,西安公众网,西安,陕西,CN,202.100.1.* xa.sn.cn,西安公众网,西安,陕西,CN,202.100.2.* xa.sn.cn,西安公众网,西安,陕西,CN,202.100.3.* xa.sn.cn,西安公众网,西安,陕西,CN,202.100.4.* xa.sn.cn,西安公众网,西安,陕西,C…
神同步!美国三地 Tesla 车主,自动驾驶都撞了警车
来源 | HyperAI超神经(ID:HyperAI)内容概要:上周在美国北卡州发生了一起交通事故,一辆自动驾驶模式下的 Tesla 撞击了停靠在路边的警车,虽未造成人员伤亡,但车辆损毁严重。事故调查中发现&#…

Q币才是腾讯真正的世界级产品
本文受《虚拟货币将是下一个大平台》启发而来。何玺认为,腾讯Q币本身就具有全球化虚拟货币的基因。 日前,有媒体报道了Pocket Change获得了由Google Ventures领投的500万美元A轮融资,使其融资总额达到640万美元。 Pocket Change是一个为Andro…

解决Office互操作错误检索COML类工厂中 CLSID为 {xxx}的组件时失败,原因是出现以下错误: 80070005...
Excel为例(其他如Word也适用)文件数据导入时报出以下错误: 检索COML类工厂中 CLSID为 {00024500-0000-0000-C000-000000000046}的组件时失败,原因是出现以下错误: 80070005,如图所示: 可以看到报出的异常类型为:UnauthorizedAcces…

再论制硬盘逻辑锁
姜卓睿 雷必武 一、序言 由于教学工作需要,本人在参看了贵刊98年第4期《硬盘逻辑锁技术研究及应用》与99年第3期《解开硬盘逻辑死锁的一种有效方法》的文章之后,决定以同类方法尝试一下,结果未获得成功,又“苦于”没有KV300 L …
我国科学家成功研制全球神经元规模最大的类脑计算机
来源 | 之江实验室(ID:zhejianglab)9月1日,浙江大学与之江实验室举办成果发布会,共同发布我国首台基于自主知识产权类脑芯片的类脑计算机(Darwin Mouse)。浙江大学校长吴朝晖院士出席并讲话。他…

批处理获取目录下所有文件名
由于要处理一些文件,找了个这样的批处理: 输出目录及子目录下所有的jpg图片的文件名,不含扩展名 1 echo off 2 cd.>List.txt 3 for /f "delims" %%i in (dir /s/a-d /b *.jpg) do >>List.txt echo %%~ni>>JustName.…

1001: 整数求和
描述:求两个整数之和输入:输入数据只包括两个整数A和B。输出:两个整数的和。样例输入:1 2样例输出:3考点:运算符代码: #include <stdio.h> int main() {int a,b;int c;scanf("%d",&a);scanf("%d",&b);cab;printf("%d",…

ASP.NET 2.0 中的新增安全功能
发布日期: 8/26/2004| 更新日期: 8/26/2004Stephen Walther Microsoft Corporation 适用于: Microsoft ASP.NET 2.0 Microsoft ASP.NET framework Microsoft SQL Server Microsoft Visual Studio .NET 摘要:ASP.NET 2.0 包含一些新…
GitHub 标星 20000+,国产 AI 开源从算法开始突破 | 专访商汤联合创始人林达华
作者 | 阿司匹林责编 | 李雪敬封图 | CSDN 下载自视觉中国作为已经有4000多名员工的AI独角兽,商汤的一举一动备受关注。从2018年开始,奔着“开源、统一、可复现”的目标,商汤开始建设人工智能算法的开源体系。当时,商汤联合创始人…

那些年,我们一起学过的汇编----之伪指令
弄懂了前面几篇关于基础的文章,下面就开始我们真正的汇编之旅了,在这一篇中我们着重来强调下汇编语言的伪指令。伪指令是汇编语言程序设计中的一个主要的部分,属于控制命令,在汇编语言中的数据定义、存储单元分配、指示程序结果等…

JavaScript-数据引用类型对象
1 <!DOCTYPE html>2 <html>3 <head lang"en">4 <meta charset"UTF-8">5 <title></title>6 </head>7 <body>8 <script>9 //按值传递:两个变量间赋值时,或将变量作为参数传入函数时,其实…
热点 | Excel不“香”了,数据分析首选Pyhton!
Excel一直在求职中有着不可动摇的地位无论是投行、咨询、四大曾经都会在JD中明确要求会Excel,而Excel称霸的时代已经过去!事实上,为了追求更高的效率和质量,他们开始使用比Excel更高效的Python,随后交易收入增长了15%。…

ASP.NET中实现打印
怎样才可以调用打印机进行打印并且对纸张类型进行设置呢? --------------------------------------------------------------- <OBJECT id"WebBrowser" height"0" width"0" classid"CLSID:8856F961-340A-11D0-A96B-00…
you have new email in /var/spool/mail/root/
有时在进入系统的时候经常提示You have new mail in /var/spool/mail/root 解决方法:修改系统配置文件/etc/profile,告诉系统不要去检查邮箱. 具体操作: 命令行输入:echo "unset MAILCHECK" >> /etc/profile 【把…

写时复制,写时拷贝,写时分裂,Copy on write
2019独角兽企业重金招聘Python工程师标准>>> 写时复制,写时拷贝,写时分裂 (Copy-on-write,简称COW)是计算机资源管理方面的一种优化技术,有着广泛的应用,比如内存管理(进…

C#生成pdf的源代码
作者:qieyj(温馨港湾) http://search.csdn.net/Expert/topic/1256/1256076.xml?temp.1866419//write by wenhui.orgusing System;using System.IO;using System.Text;using System.Collections; namespace PDFGenerator{ public class PDFGenerator{static fl…
迁移性好、多用途,港中文提出特征分离的无监督人类三维姿态表征
来源 | 我爱计算机视觉(ID:aicvml)本文将介绍一种基于特征分离的通用人类姿态特征的学习算法Unsupervised Human 3D Pose Representation with Viewpoint and Pose Disentanglement。该算法从无监督的特征分离过程中,习得了一个迁移性好、多用…

解決Linux下Android开发真机调试设备不被识别问题
为什么80%的码农都做不了架构师?>>> 在google找了不少关于这个的资料,各种添加和修改系统文件,但是我的defy依旧没有被识别。尼马的! 好吧,是我低估了Android的sdk的adb调试工具,其实简单的两个…

在Server 2003上部署IIS+PHP+MySQL配置清单
在Server 2003上部署IISPHPMySQL I.安装Windows Server 2003 将光盘放入光驱中,设置BIOS,从CDROM引导加载安装程序,等待启动; 设置注册信息,名字和公司组织名; 填写安装密钥; 设置远程连接数目&…
用Python打造一款文件搜索工具,所有功能自己定义
前言在日常的办公中,我们经常会从一堆不同格式的文件(夹)中搜索特定的文件,可能你是凭着记忆去找或是借助软件,但你有想过如何用Python实现吗?本文将基于几个常见的搜索操作讲解。扫描路径内的内容有些时候我们会希望在当前文件夹…

vlan间路由实验
路由与交换技术实验报告 实验7 vlan间路由实验 班级:130462 姓名:张欣国 学号:13046210 一、 实验目的 1. 了解vlan间路由的不同方法; 2. 了解路由备份; 二、 实验步骤与内容 1. 详细阅读操作过程,认真完…

.net中连接SYBASE的种种问题
作者:zwztu http://search.csdn.net/Expert/topic/1612/1612693.xml?temp.2369806首先如果用OLEDB连呢?如果用ASE 的OLEDB 提供者,那这个提供者哪里有下呢? 其次如果用MSDATASHAPE连,可以是可以,…