首页 > 其他 > 详细

设计模式之原型模式

时间:2020-10-08 18:44:36      阅读:50      评论:0      收藏:0      [点我收藏+]

    这节讲一下原型模式,原型模式用于解决大量相同或相似对象的创建问题,传统的,我们实例化对象要用new关键字,在面对大量重复对象的创建情况下,new实例的过程是比较消耗资源的,所以我们可以利用一个对象作为原型,通过这个对象的不断克隆自己来产出一个个新实例(这跟js的原型对象并不相同,读者不要跟其做理论比较)。

    我们可以设想一下,为何克隆比new实例要高效:拿画画来说,new实例相当于每次要构思这幅画,并将其画出来,克隆相当于第一次构思并画出后,后续的画都是临摹,所以克隆是高效的。

    我们看一下原型模式的定义:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。

    在示例代码之前,先要理解一个概念:深拷贝和浅拷贝:

    所谓浅拷贝就是指拷贝时只拷贝值类型的属性,引用类型的属性地址跟原型对象的地址指向一致,而深拷贝就是将原型对象的值类型和引用类型的属性都拷贝一份,可以说是和原型对象完全分离开来。

    接下来我们看一下如何让一个对象可被克隆:

class prototypeClass : ICloneable
{
    public prototypeClass(string classname)
    {
        this.classname = classname;
    }
    public object Clone()
    {
        return MemberwiseClone();
    }
?
    public string classname { get; set; }
?
    public void ShowName()
    {
        Console.WriteLine(classname);
    }
}

    具体的逻辑就是让原型类实现ICloneable接口,实现接口的Clone()方法,方法中调用MemberwiseClone()返回一个基于该原型对象浅拷贝的对象。

    在主方法中调用,我们查看一下运行结果:

prototypeClass p = new prototypeClass("小明");
prototypeClass p_clone = (prototypeClass)p.Clone();
p.ShowName();
p_clone.ShowName();
Console.WriteLine(p == p_clone);

技术分享图片

    下面我再添加一个类,并在prototypeClass类中添加这个类作为属性:

 

技术分享图片

技术分享图片

    在主方法中比较一下克隆对象的s属性是否与原型对象的s属性相等:

技术分享图片

   运行结果如下:

技术分享图片

    结果为true,这就证明了此为浅拷贝。

    若要实现深拷贝,需做点改动:

static prototypeClassS ps=new prototypeClassS("小艾");
public object Clone()
{
    prototypeClass p=(prototypeClass) MemberwiseClone();
    p.s=(prototypeClassS)ps.Clone();//手动调用属性的克隆方法实现深度拷贝
    return p;
}

     加入一个静态原型属性,每次克隆该原型对象时都去手动将引用对象克隆出来并赋值,如果被拷贝的属性自己也有引用类型的属性,为了实现深拷贝,也得做对应的修改,这样就形成了一个拷贝链,层层深入,从而完成深度拷贝(其实这挺繁琐的)。

    

    下面我通过代码来演示一下new实例和克隆的性能差距:

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 100000; i++)
{
    prototypeClass clone = (prototypeClass)p.Clone();
}
?
stopwatch.Stop();
Console.WriteLine("克隆时间:" + stopwatch.Elapsed);
?
stopwatch.Start();
for (int i = 0; i < 100000; i++)
{
    prototypeClass clone = new prototypeClass("小明",new prototypeClassS("新二"));
}
stopwatch.Stop();
Console.WriteLine("new 实例:" + stopwatch.Elapsed);

    在主方法中编写上述代码,下面看一下运行结果:

技术分享图片

    差距不言而喻。

 

    当然,原型模式也有缺点:

  • 我们需要为每一个类都配置一个 clone 方法,clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。

  • 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。

  个人公众号,热爱分享,知识无价。

技术分享图片

 

设计模式之原型模式

原文:https://www.cnblogs.com/charlesmvp/p/13782143.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!