C#原型模式(深拷贝、浅拷贝)
原型模式就是用于创建重复的对象,当想要创建一个新的对象但是开销比较大或者想将对象的当前状态保存下来的时候,我们就可以使用原型模式。
创建原型
public abstract class Base
{
//因为String的特殊性,所以此次演示我们使用StringBuilder
public StringBuilder Name { get; set; }
public int Age { get; set; } public Base()
{
//模拟创建对象花费的开销
Thread.Sleep();
} public Base(String name, int age)
{
this.Name = new StringBuilder(name);
this.Age = age;
//模拟创建对象花费的开销
Thread.Sleep();
} //深拷贝
public abstract Base Clone();
//浅拷贝
public abstract Base MClone();
}
接下来创建一个Peron类,继承Base,并且实现两个复制方法
//如果是要通过序列化来进行深拷贝的话,要打上Serializable标签
[Serializable]
public class Person : Base
{
public Person()
: base()
{ }
public Person(String name, int age)
: base(name, age)
{ }
/// <summary>
/// 深拷贝
/// </summary>
/// <returns>返回一个全新的Person对象</returns>
public override Base Clone()
{
//创建一个内存流
MemoryStream ms = new MemoryStream();
//创建一个二进制序列化对象
BinaryFormatter bf = new BinaryFormatter();
//将当前对象序列化写入ms内存流中
bf.Serialize(ms, this);
//设置流读取的位置
ms.Position = ;
//将流反序列化为Object对象
return bf.Deserialize(ms) as Person;
} /// <summary>
/// 浅拷贝
/// </summary>
/// <returns></returns>
public override Base MClone() =>
//浅拷贝
this.MemberwiseClone() as Person;
}
Main方法中调用,首先我们每次都创建新的Person对象
static void Main(string[] args)
{
//用于计时
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start(); Person p = new Person("a",2);
Person p2 = new Person("a",);
Person p3 = new Person("a",2); stopwatch.Stop();
Console.WriteLine("耗时:"+stopwatch.Elapsed);
Console.ReadKey();
}
运行结果:

可见如果创建对象如果开销很大的话,每次用的时候都创建效率就会很低
接下来我们使用原型模式来创建重复的对象,调用MClone()浅拷贝
static void Main(string[] args)
{
//用于计时
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start(); Person p = new Person("a",);
Person p1 = p.MClone() as Person;
Person p2 = p.MClone() as Person; //记录下来name的值,后续通过即时窗口查看
StringBuilder name2 = p2.Name;
StringBuilder name1 = p1.Name; stopwatch.Stop();
Console.WriteLine("耗时:"+stopwatch.Elapsed);
Console.ReadKey();
}
在Console.ReadKey();处设置断点,运行程序,打开 调试>>窗口>>即时,在右下角即时窗口输入 *&name1 回车,*&name2 回车,查看name1和name2的内存地址

我们可以看到,name1和name2的内存地址都是相同的,说明p2.Name和p1.Name是指向了同一个引用。所以对于属性是引用类型的对象,实现浅拷贝,所有的属性引用只会指向同一个对象,也就是说只要有一个对象修改了Name属性,其他的对象的Name属性都会发生改变。
看一下运行结果

可以发现,只有第一次创建对象需要很大的开销,通过原型复制的话是很快的。
接下来我们看一下深拷贝
static void Main(string[] args)
{
//用于计时
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start(); Person p = new Person("a",);
Person p1 = p.Clone() as Person;
Person p2 = p.Clone() as Person; //记录下来name的值,后续通过即时窗口查看
StringBuilder name2 = p2.Name;
StringBuilder name1 = p1.Name; stopwatch.Stop();
Console.WriteLine("耗时:"+stopwatch.Elapsed);
Console.ReadKey();
}
执行和刚才相同的操作,来看一下内存地址

可以发现,p1和p2的Name在内存中的地址是不一样的, 就是说明深拷贝会将对象的所有非静态属性都复制一份,如果碰到引用类型也会重新创建一份,而不是复制指向对象的引用。
最后我们看一下运行结果

C#原型模式(深拷贝、浅拷贝)的更多相关文章
- Prototype 原型模式 复制 浅拷贝 clone MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Java原型模式之浅拷贝-深拷贝
一.是什么? 浅拷贝:对值类型的成员变量进行值的复制,对引用类型的成员变量仅仅复制引用,不复制引用的对象 深拷贝:对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制 内部机制: ...
- 设计模式:原型模式介绍 && 原型模式的深拷贝问题
0.背景 克隆羊问题:有一个羊,是一个类,有对应的属性,要求创建完全一样的10只羊出来. 那么实现起来很简单,我们先写出羊的类: public class Sheep { private String ...
- Java原型模式之基础
一.是什么? 定义:用原型实例指定创建对象的种类,而且通过拷贝这些原型创建新的对象.(官方定义) 原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype. Prototype类须要 ...
- 设计模式学习-使用go实现原型模式
原型模式 定义 代码实现 优点 缺点 适用场景 参考 原型模式 定义 如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复 ...
- C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝
原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一 ...
- 设计模式_11_原型模式(prototype)深拷贝、浅拷贝
设计模式_11_原型模式(prototype) 浅拷贝: package designPatternOf23; /** * 定义:用原型实例,指定创建对象的种类,并通过拷贝这些原型创建新的对象 * P ...
- 设计模式之原型模式(深入理解OC中的NSCopying协议以及浅拷贝、深拷贝)
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.原型模式其实就是从一个对象再创建另一个可定制的对象,而且不需知道任何创建的细节. 比如说,有一个Person类,有firstN ...
- Java clone克隆方法 --深拷贝--浅拷贝 --原型模型
什么是深拷贝? 什么是浅拷贝? 创建一个对象的方法有几种? 默认的Object方法中的clone是深拷贝还是浅拷贝? 为什么说很多深拷贝都是不彻底的深拷贝? 什么是原型模型,什么是原型模式? 原型模型 ...
随机推荐
- 特征金字塔网络Feature Pyramid Networks
小目标检测很难,为什么难.想象一下,两幅图片,尺寸一样,都是拍的红绿灯,但是一副图是离得很近的拍的,一幅图是离得很远的拍的,红绿灯在图片里只占了很小的一个角落,即便是对人眼而言,后者图片中的红绿灯也更 ...
- Tomcat 简单容器化
Tomcat 容器化 思考 问题1 , Tomcat 容器化,Tomcat 如何配置 APR 连接器 Tomcat 的基础镜像已经是开启了 APR. 问题2, Tomcat 是每次都需要重新构建. 一 ...
- Jar 打包与执行
Java学习笔记之一,用于个人记录.整理自<Head First Java>. 假设有如下目录结构: 程序入口在 Jukebox8.java.这个代码文件开头是有如下这样的包声明语句的: ...
- [笔记] vs code 设置终端
设置文件: setting.json 1 设置自定义终端 cmd "terminal.integrated.shell.windows": "C:\\WINDOWS\\S ...
- iis7 下配置 ASP.NET MVC 项目遇到的问题 (WIN7 64位 旗舰版 第一次配置站点)
转自 https://www.cnblogs.com/Leo_wl/p/3866625.html,再次感谢 指定的目录或文件在 Web 服务器上不存在. URL 拼写错误. 某个自定义筛选器或模块(如 ...
- easyui高级控件
开发模式 1. 美工(ui工程师:出一个项目模型) java工程师:将原有的html转成jsp,动态展示数据 缺点: 客户需要调节前端的展示效果 解决:由美工去重新排版,重新选色.2.前后端分离 美工 ...
- java 学习 进阶之 一 (线程基础)
一.线程安全 线程安全的概念:当多个线程访问某一个类(对象或方法)时.这个类始终都能表现出正确的行为那么这个类(对象或方法)就是线程安全的. synchronized:可以在任何对象及方法上加锁,而加 ...
- Can't toast on a thread that has not called Looper.prepare()
Android开发中Can't toast on a thread that has not called Looper.prepare()问题 说一下问题出现场景: 在一个Android项目中,利用 ...
- [b0010] windows 下 eclipse 开发 hdfs程序样例 (二)
目的: 学习windows 开发hadoop程序的配置 相关: [b0007] windows 下 eclipse 开发 hdfs程序样例 环境: 基于以下环境配置好后. [b0008] Window ...
- centos6.8下hadoop3.1.1完全分布式安装指南
前述:这篇文档是建立在三台虚拟机相互ping通,防火墙关闭,hosts文件修改,SSH 免密码登录,主机名修改等的基础上开始的. 一.传入文件 1.创建安装目录 mkdir /usr/local/so ...