当前位置:   article > 正文

C#编程模式之原型模式

C#编程模式之原型模式

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

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

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

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

  1. /// <summary>
  2. /// 原型类
  3. /// </summary>
  4. [Serializable]
  5. public abstract class CPrototype
  6. {
  7. /// <summary>
  8. /// 值类型测试
  9. /// </summary>
  10. public string strMessage { get; set; }
  11. /// <summary>
  12. /// 引用类型测试
  13. /// </summary>
  14. public Dictionary<int, string> dicKeyValuePairs = new Dictionary<int, string>() { };
  15. /// <summary>
  16. /// 构造函数
  17. /// </summary>
  18. /// <param name="strMsgInfo"></param>
  19. public CPrototype(string strMsgInfo)
  20. {
  21. this.strMessage = strMsgInfo;
  22. }
  23. /// <summary>
  24. /// 复制函数
  25. /// </summary>
  26. /// <returns></returns>
  27. public abstract CPrototype Clone();
  28. /// <summary>
  29. /// 获取属性信息
  30. /// </summary>
  31. /// <returns></returns>
  32. public abstract string GetAttributeInfo();
  33. }

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

  1. /// <summary>
  2. /// 创建具体的原型(浅拷贝)
  3. /// </summary>
  4. public class CShallowClone : CPrototype
  5. {
  6. /// <summary>
  7. /// 构造函数
  8. /// </summary>
  9. /// <param name="strMsgInfo"></param>
  10. public CShallowClone(string strMsgInfo) : base(strMsgInfo) { }
  11. /// <summary>
  12. /// 实现圆形接口,进行原型拷贝
  13. /// </summary>
  14. /// <returns></returns>
  15. /// <exception cref="NotImplementedException"></exception>
  16. public override CPrototype Clone()
  17. {
  18. return (CPrototype)this.MemberwiseClone();
  19. }
  20. /// <summary>
  21. /// 实现获取属性信息的方法
  22. /// </summary>
  23. /// <returns></returns>
  24. /// <exception cref="NotImplementedException"></exception>
  25. public override string GetAttributeInfo()
  26. {
  27. string strReturn = string.Empty;
  28. strReturn = string.Format("strMessage:{0}", this.strMessage);
  29. foreach (KeyValuePair<int, string> item in this.dicKeyValuePairs)
  30. {
  31. strReturn += "\r\n" + string.Format("KEY:{0} Value:{1}", item.Key, item.Value);
  32. }
  33. return strReturn;
  34. }
  35. }

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

  1. /// <summary>
  2. /// 创建具体的原型(深拷贝)
  3. /// </summary>
  4. [Serializable]
  5. public class CDeepClone : CPrototype
  6. {
  7. /// <summary>
  8. /// 构造函数
  9. /// </summary>
  10. /// <param name="strMsgInfo"></param>
  11. public CDeepClone(string strMsgInfo) : base(strMsgInfo) { }
  12. /// <summary>
  13. /// 实现圆形接口,进行原型拷贝
  14. /// </summary>
  15. /// <returns></returns>
  16. /// <exception cref="NotImplementedException"></exception>
  17. public override CPrototype Clone()
  18. {
  19. //创建一个内存流
  20. MemoryStream memoryStream = new MemoryStream();
  21. //创建一个二进制序列化对象
  22. BinaryFormatter binaryFormatter = new BinaryFormatter();
  23. //将当前对象序列化写入ms内存流中
  24. binaryFormatter.Serialize(memoryStream, this);
  25. //设置流读取的位置
  26. memoryStream.Position = 0;
  27. //将流反序列化为Object对象
  28. return binaryFormatter.Deserialize(memoryStream) as CPrototype;
  29. }
  30. /// <summary>
  31. /// 实现获取属性信息的方法
  32. /// </summary>
  33. /// <returns></returns>
  34. /// <exception cref="NotImplementedException"></exception>
  35. public override string GetAttributeInfo()
  36. {
  37. string strReturn = string.Empty;
  38. strReturn = string.Format("strMessage:{0}", this.strMessage);
  39. foreach (KeyValuePair<int, string> item in this.dicKeyValuePairs)
  40. {
  41. strReturn += "\r\n" + string.Format("KEY:{0} Value:{1}", item.Key, item.Value);
  42. }
  43. return strReturn;
  44. }
  45. }

        4、客户端的分别调用。

  1. /// <summary>
  2. /// 原型浅拷贝
  3. /// </summary>
  4. /// <param name="sender"></param>
  5. /// <param name="e"></param>
  6. private void btn_shallowclone_Click(object sender, EventArgs e)
  7. {
  8. CShallowClone cShallowClone = new CShallowClone("ShallowCloneTest");
  9. cShallowClone.dicKeyValuePairs.Add(1, "TestOne");
  10. cShallowClone.dicKeyValuePairs.Add(2, "TestTwo");
  11. tbox_shallowclone.Text = "第一次打印原型:" + cShallowClone.GetAttributeInfo();
  12. CShallowClone cShallowCloneCopy = (CShallowClone)cShallowClone.Clone();
  13. cShallowCloneCopy.strMessage = "ShallowCloneTestCopy";
  14. cShallowCloneCopy.dicKeyValuePairs[1] = "TestOneEdit";
  15. tbox_shallowclone.Text += "\r\n打印拷贝的类型:" + cShallowCloneCopy.GetAttributeInfo();
  16. tbox_shallowclone.Text += "\r\n第二次打印原型:" + cShallowClone.GetAttributeInfo();
  17. }
  18. /// <summary>
  19. /// 原型深拷贝
  20. /// </summary>
  21. /// <param name="sender"></param>
  22. /// <param name="e"></param>
  23. private void btn_deepclone_Click(object sender, EventArgs e)
  24. {
  25. CDeepClone cDeepClone = new CDeepClone("DeepCloneTest");
  26. cDeepClone.dicKeyValuePairs.Add(1, "TestOne");
  27. cDeepClone.dicKeyValuePairs.Add(2, "TestTwo");
  28. tbox_deepclone.Text = "第一次打印原型:" + cDeepClone.GetAttributeInfo();
  29. CDeepClone cDeepCloneCopy = (CDeepClone)cDeepClone.Clone();
  30. cDeepCloneCopy.strMessage = "DeepCloneTestCopy";
  31. cDeepCloneCopy.dicKeyValuePairs[1] = "TestOneEdit";
  32. tbox_deepclone.Text += "\r\n打印拷贝的类型:" + cDeepCloneCopy.GetAttributeInfo();
  33. tbox_deepclone.Text += "\r\n第二次打印原型:" + cDeepClone.GetAttributeInfo();
  34. }

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

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/487349
推荐阅读
相关标签
  

闽ICP备14008679号