C#实现原型模式

Posted 小小架构师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#实现原型模式相关的知识,希望对你有一定的参考价值。

原型模式是指通过拷贝原有对象来创建新的对象,以减少new一个新对象的资源开销。 今天我们就来看下如何在C#中使用原型模式,Follow me!
假如有这样一个需求:需要导出一万名学生资料到Excel中,一般代码会这样写:
C#实现原型模式
上面的代码其实也没有什么问题,但如果数量级换成百万或千万,则频繁的创建对象会对性能造成很大的影响。而且学生对象中有部分字符都是一样的,比如Address。这时我们就需要使用原型模式来减少对象的创建了。在C#中其实就是使用ICloneable接口并实现Clone方法。代码如下:
C#实现原型模式
上面的代码非常简单,主要调用当前对象的MemberwiseClone()方法,这个方法其实就是拷贝对象的内存流,我们看下源代码。如下:
C#实现原型模式
我们接着改下使用的地方,将原来new的代码改成clone方法。代码如下:
C#实现原型模式
上面的代码中,我们先new一个模板对象,然后以这个模板对象为基础,不停的拷贝产生新对象,这样就从new一万次变为new一次了,性能提升杠杠的。
到这里,C#中实现原型模式就讲完了,是不是特别简单?不过我们还要再补充一个点,就是浅拷贝和深拷贝,如果你对这块已经很了解了,就不用往下读了。想了解的继续,Follow me!
我们上面通过MemberwiseClone()方法实现的其实是对象的浅拷贝,大家应该都知道浅拷贝和深拷贝的区别。简单来说,如果对象的字段是复杂类型的话,浅拷贝只会拷贝这个字段的引用,而深拷贝会重新创建这个复杂类型的字段。
比如上面代码中学生的Address字段,就是一个复杂类型,通过Clone方法得到的一万个学生对象的Address其实都是指的同一个对象。如下图:
C#实现原型模式
这样就会有问题,如果修改某一个学生的地址,则所有的学生地址都会变掉,这是我们不想看到的。如下:
C#实现原型模式
对此,我们可以使用深拷贝来解决。一般实现深拷贝的方法有二进制序列化、反射等。我们先看下使用二进制序列化的方式,代码如下:
C#实现原型模式
上面的代码中,我定义了一个IDeepCopy接口,然后让Student类实现它,在DeepCopy()方法中,我们使用BinaryFormatter操作流实现深拷贝。有一个地方要注意,就是Student类和Address类上面需要加上[Serializable]特性,不然不可以序列化的。
接着,我们再来讲一下使用反射来实现深拷贝,其实就是逐层遍历字段并赋值。代码如下:

这里定义了一个DeepCopyByReflect()泛型方法,这个方法中主要使用反射进行遍历每个字段,如果字段是复杂类型,则递归调用DeepCopyByReflect方法,直到所有的字段都为基本类型。
以上讲了二进制序列和反射方法实现深拷贝。其实我们也可以简单使用json序列化的方法,更简单,代码如下:
终于讲完了,好累呀!最后简单总结下:
  • 实际编码中如果出现循环创建对象的场景,就要考虑是否可以使用原型模式

  • 大部分场景下我们只要使用浅拷贝就行,深拷贝毕竟涉及到反射或序列化这些


如果能帮到你一点点,就给个赞吧,或者关注我。 哈哈~~

以上是关于C#实现原型模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之原型模式

C#设计模式:原型模式(Prototype)及深拷贝浅拷贝

C#设计模式——原型模式

C#设计模式:原型模式(Prototype Pattern)

c# 24种设计模式5原型模式(Prototype)

c#设计模式-创建性模式-3.原型模式