原型模式

什么是原型模式

原型模式:通过克隆原型类实例化的对象,从而创建新的对象

如何使用

让类实现 ICloneable 接口。

class Resume : ICloneable
{
    string name;
    string sex;
    string age;
    public Resume(string name)
    {
        this.name = name;
    }
    //设置个人信息
    public void SetPersonalInfo(string sex,string age)
    {
        this.sex = sex;
        this.age = age;
    }
    //实现接口的Clone方法
    public object Clone()
    {
        return (Object)this.MemberwiseClone();
    }
    public void Display()
    {
        Console.WriteLine("{0} {1} {2}",name,sex,age);
    }
}

其中,MemberwiseClone()方法是基类 Object 的一个方法,用来创建当前对象的浅表副本,即实现对象的浅复制。
该方法会创建一个新对象,然后将当前对象的非静态字段复制到新对象。如果字段是值类型,则会把数据复制到新对象中;如果字段是引用类型,则只复制引用但不复制引用的对象,当前对象和新对象仍然指向堆上的同一个对象。

★为什么是复制非静态字段呢?
首先要明白静态字段和非静态字段的区别是什么。
静态字段:类中所有对象共享的字段,通过【类名.字段名】 访问
非静态字段:为每个对象所私有,即每个对象的字段值互不影响,通过【对象名.字段名】访问
所以复制的是非静态字段,而静态字段大家都能用,没必要复制。

用在哪?

个人理解:当我们需要创建同一个类的很多个对象时,就可以通过这种克隆的方式,来创建对象。而且还可以对每个对象单独修改,而不影响其他的对象。

优缺点

  优点:①提高性能。通过原型模式创建对象的时候,不需要用构造函数一个个实例化创建,如果构造函数的执行时间很长的话,通过克隆可以大大提高性能。
  缺点:①如果引用很多层,想要实现深复制的话,需要把每一层的引用类型都复制一遍,实现比较麻烦。②如果想要更改 Clone() 方法,则需要修改类,违背了“开闭原则”。

浅复制 vs 深复制
//浅复制代码
class Resume : ICloneable
{
    string name;
    private WorkExperience work;
    public Resume(string name)
    {
        this.name = name;
        work = new WorkExperience();
    }
    //设置工作经历
    public void SetWorkExperience(string workDate,string company)
    {
        work.WorkDate = workDate;
        work.Company = company;
    }
    public object Clone()
    {
        return (Resume)this.MemberwiseClone();
    }
    public void Display()
    {
        Console.WriteLine("{0}",name);
        Console.WriteLine("工作经历: {0} {1}",work.WorkDate,work.Company);
    }
}
class WorkExperience : ICloneable
{
    string _workDate;
    string _company;
    public string WorkDate
    {
        set { _workDate = value; }
        get { return _workDate; }
    }
    public string Company
    {
        set { _company = value; }
        get { return _company; }
    }
}

//客户端的代码
static void Main(string[] args)
{
    Resume a = new Resume("大鸟");
    a.SetWorkExperience("1998-2000", "xx公司");

    Resume b = (Resume)a.Clone();
    b.SetWorkExperience("1998-2006", "YY公司");

    Resume c = (Resume)a.Clone();
    c.SetWorkExperience("1998-2003", "ZZ公司");

    a.Display();
    b.Display();
    c.Display();

    Console.ReadKey();
}
//output(三个相同):
//大鸟 工作经历:1998-2003 ZZ公司

浅复制:当字段是引用类型的时候,只复制引用而不复制引用的对象。
这里写图片描述

//深复制代码
class Resume : ICloneable
{
    string name;
    private WorkExperience work;
    public Resume(string name)
    {
        this.name = name;
        work = new WorkExperience();
    }
    private Resume(WorkExperience work)
    {
        this.work = (WorkExperience)work.Clone();            
    }
    //设置工作经历
    public void SetWorkExperience(string workDate,string company)
    {
        work.WorkDate = workDate;
        work.Company = company;
    }
    //深复制的clone方法实现与浅复制不同
    public object Clone()
    {
        //重新实例化一个Resume对象,调用Resume的私有构造方法,将原型的work对象赋值给【复制的Resume的work对象】
        Resume obj = new Resume(this.work);
        //将原型其他的字段的值也赋值给复制的 Resume 对象
        obj.name = this.name;
        obj.sex = this.sex;
        obj.age = this.age;
        return obj;
    }
    public void Display()
    {
        Console.WriteLine("{0}",name);
        Console.WriteLine("工作经历: {0} {1}",work.WorkDate,work.Company);
    }
}
class WorkExperience : ICloneable
{
    string _workDate;
    string _company;
    public string WorkDate
    {
        set { _workDate = value; }
        get { return _workDate; }
    }
    public string Company
    {
        set { _company = value; }
        get { return _company; }
    }
    //增添了Clone()方法,用来创建WorkExperience的浅表对象
    public object Clone()
    {
        return (Object)this.MemberwiseClone();
    }
}
//客户端代码同浅复制,这样各对象显示出来的就不一样了

深复制:当字段是引用类型的时候,不仅复制引用,也复制引用的对象
这里写图片描述
★string也是引用类型,按正常来说浅复制之后,它们都共用一个引用对象,但是为什么改变字段的内容之后,它们互不影响呢?
推荐大家看一下这篇博客:String到底是值类型还是引用类型(c#),相信大家看完之后就明白了。

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值