C#编程模式之原型模式

news/2024/10/9 3:31:18/

        模式介绍:各位朋友,我们继续探讨C#的编程模式,本文介绍原型模式原型模式的本质,其实就拷贝加创建一个新的实例。那可能就会由朋友问了,这么简单的原理,直接New一个新的实例,然后把原型类赋值给新类不香么?朋友,确实可以这样,但是原型模式存在的意义远不止于此,且听我娓娓道来。

        首先从应用来说,很多时候,我们New一个新的实例,会消耗很多资源或者耗费很多时间,我们使用原型模式的时候,就能省去耗时耗力的操作。举个最常见的例子,也是最常用的使用场景,对对象的历史节点进行保存,比如在一系列操作之后,进行状态的复制保存,或者恢复历史状态、撤销操作等。

        本质和应用我们有所了解之后,就看看具体的实现了。说到复制,我们知道有深复制和浅复制两种,其区别在下文中有关于程序运行结果的详细分析,接下来见证奇迹的时候到了,用一个例子来实现两种方式,上代码!!!

        1、创建原型类。用来规范具体的原型。这里直接增加[Serializable]标签,浅复制不会使用,但是深度复制会用到序列化和反序列化,就提起准备了,如果你的代码中不需要进行深度复制,就可以不用加此标签。

    /// <summary>/// 原型类/// </summary>[Serializable]public abstract class CPrototype{/// <summary>/// 值类型测试/// </summary>public string strMessage { get; set; }/// <summary>/// 引用类型测试/// </summary>public Dictionary<int, string> dicKeyValuePairs = new Dictionary<int, string>() { };/// <summary>/// 构造函数/// </summary>/// <param name="strMsgInfo"></param>public CPrototype(string strMsgInfo){this.strMessage = strMsgInfo;}/// <summary>/// 复制函数/// </summary>/// <returns></returns>public abstract CPrototype Clone();/// <summary>/// 获取属性信息/// </summary>/// <returns></returns>public abstract string GetAttributeInfo();}

        2、创建具体的原型(浅拷贝模式)。

    /// <summary>/// 创建具体的原型(浅拷贝)/// </summary>public class CShallowClone : CPrototype{/// <summary>/// 构造函数/// </summary>/// <param name="strMsgInfo"></param>public CShallowClone(string strMsgInfo) : base(strMsgInfo) { }/// <summary>/// 实现圆形接口,进行原型拷贝/// </summary>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public override CPrototype Clone(){return (CPrototype)this.MemberwiseClone();}/// <summary>/// 实现获取属性信息的方法/// </summary>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public override string GetAttributeInfo(){string strReturn = string.Empty;strReturn = string.Format("strMessage:{0}", this.strMessage);foreach (KeyValuePair<int, string> item in this.dicKeyValuePairs){strReturn += "\r\n" + string.Format("KEY:{0}  Value:{1}", item.Key, item.Value);}return strReturn;}}

        3、创建具体的原型(浅拷贝模式)。

    /// <summary>/// 创建具体的原型(深拷贝)/// </summary>[Serializable]public class CDeepClone : CPrototype{/// <summary>/// 构造函数/// </summary>/// <param name="strMsgInfo"></param>public CDeepClone(string strMsgInfo) : base(strMsgInfo) { }/// <summary>/// 实现圆形接口,进行原型拷贝/// </summary>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public override CPrototype Clone(){//创建一个内存流MemoryStream memoryStream = new MemoryStream();//创建一个二进制序列化对象BinaryFormatter binaryFormatter = new BinaryFormatter();//将当前对象序列化写入ms内存流中binaryFormatter.Serialize(memoryStream, this);//设置流读取的位置memoryStream.Position = 0;//将流反序列化为Object对象return binaryFormatter.Deserialize(memoryStream) as CPrototype;}/// <summary>/// 实现获取属性信息的方法/// </summary>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public override string GetAttributeInfo(){string strReturn = string.Empty;strReturn = string.Format("strMessage:{0}", this.strMessage);foreach (KeyValuePair<int, string> item in this.dicKeyValuePairs){strReturn += "\r\n" + string.Format("KEY:{0}  Value:{1}", item.Key, item.Value);}return strReturn;}}

        4、客户端的分别调用。

        /// <summary>/// 原型浅拷贝/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_shallowclone_Click(object sender, EventArgs e){CShallowClone cShallowClone = new CShallowClone("ShallowCloneTest");cShallowClone.dicKeyValuePairs.Add(1, "TestOne");cShallowClone.dicKeyValuePairs.Add(2, "TestTwo");tbox_shallowclone.Text = "第一次打印原型:" + cShallowClone.GetAttributeInfo();CShallowClone cShallowCloneCopy = (CShallowClone)cShallowClone.Clone();cShallowCloneCopy.strMessage = "ShallowCloneTestCopy";cShallowCloneCopy.dicKeyValuePairs[1] = "TestOneEdit";tbox_shallowclone.Text += "\r\n打印拷贝的类型:" + cShallowCloneCopy.GetAttributeInfo();tbox_shallowclone.Text += "\r\n第二次打印原型:" + cShallowClone.GetAttributeInfo();}/// <summary>/// 原型深拷贝/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_deepclone_Click(object sender, EventArgs e){CDeepClone cDeepClone = new CDeepClone("DeepCloneTest");cDeepClone.dicKeyValuePairs.Add(1, "TestOne");cDeepClone.dicKeyValuePairs.Add(2, "TestTwo");tbox_deepclone.Text = "第一次打印原型:" + cDeepClone.GetAttributeInfo();CDeepClone cDeepCloneCopy = (CDeepClone)cDeepClone.Clone();cDeepCloneCopy.strMessage = "DeepCloneTestCopy";cDeepCloneCopy.dicKeyValuePairs[1] = "TestOneEdit";tbox_deepclone.Text += "\r\n打印拷贝的类型:" + cDeepCloneCopy.GetAttributeInfo();tbox_deepclone.Text += "\r\n第二次打印原型:" + cDeepClone.GetAttributeInfo();}

        5、程序运行的效果图如下:

        基于以上运行结果,我们可以清晰的看到,浅层复制(使用this.MemberwiseClone()),对实例的值类型(string等)进行了全盘拷贝,对实例的引用类型,只拷贝了引用地址。所以浅复制,在更改引用类型时,原型实例对应的引用类型值也随之改变。

        通过序列化和反序列化进行的深度复制,会给引用类型生成一个新的地址,这样二者就彻底区别开来(感兴趣的伙伴可以尝试使用反射来进行深度拷贝)。

        总的来说,原型模式就是对对象进行复制操作,从而避免重复进行初始化操作,批量生产同一个对象的克隆体。


http://www.ppmy.cn/news/1435120.html

相关文章

n-gram模型

N-gram是一种基于统计的语言模型&#xff0c;它基于一个假设&#xff0c;即一个词的出现仅与它前面的N-1个词有关&#xff0c;而与更远的词无关。 N-gram模型通常用于自然语言处理(NLP)任务&#xff0c;如文本生成、文本分类、机器翻译、拼写检查和语音识别等。在N-gram模型中…

NL2SQL技术方案系列(6):金融领域知识检索,NL2SQL技术方案以及行业案例实战讲解4

NL2SQL技术方案系列(6):金融领域NL2SQL技术方案以及行业案例实战讲解4 NL2SQL基础系列(1):业界顶尖排行榜、权威测评数据集及LLM大模型(Spider vs BIRD)全面对比优劣分析[Text2SQL、Text2DSL] NL2SQL基础系列(2):主流大模型与微调方法精选集,Text2SQL经典算法技术回顾七…

PHP+MYSQL多条件选一通用搜索系统功能单文件7KB

通用功能: 快速填写参数用于自己的mysql数据表搜索,ajax载入数据 <?php header("content-Type: text/html; charsetUTF-8"); //error_reporting(0);$dbhost "localhost"; //数据库地址本地localhost $dbuser "chalidecom"; //数据库账号 …

yarn 会从npm config registry 下载依赖吗

Yarn 通常会使用自己配置的 registry 来下载依赖包&#xff0c;但如果在 Yarn 中没有专门配置 registry&#xff0c;它有时会默认继承 npm 的全局配置。当你执行 npm config set registry <registry-url> 设置了 npm 的 registry 后&#xff0c;若 Yarn 没有单独设置 reg…

就业班 第三阶段(负载均衡) 2401--4.19 day3

二、企业 keepalived 高可用项目实战 1、Keepalived VRRP 介绍 keepalived是什么keepalived是集群管理中保证集群高可用的一个服务软件&#xff0c;用来防止单点故障。 ​ keepalived工作原理keepalived是以VRRP协议为实现基础的&#xff0c;VRRP全称Virtual Router Redundan…

JVM (Micrometer)监控SpringBoot(AWS EKS版)

问题 怎样使用JVM (Micrometer)面板&#xff0c;监控Spring&#xff1f;这里不涉及Prometheus和Grafana&#xff0c;重点介绍与Micrometer与Springboot&#xff0c;k8s怎样集成。 pom.xml 引入依赖&#xff0c;如下&#xff1a; <properties><micrometer.version&…

1-k8s集群安装报错CGROUPS_CPU: missing

加入集群报错 [rootiZuf65r8i4e90z40vlh8mgZ ~]# kubeadm join 172.19.35.202:6443 --token 9edy1q.209zfq0387qtiv5x --discovery-token-ca-cert-hash sha256:24e0953896046aa8ce573ec7faf6609b87250883a7691fcad70a0faa81978c3b --control-plane --cri-socket "unix://…

opencv保存图片-------c++

保存图片 bool opencvTool::saveImage(const std::string path, const cv::Mat image) {if (image.empty()){std::cout << "Error: empty mat " << std::endl;return false;}// 保存图像文件try {cv::imwrite(path, image);std::cout << "Im…