设计模式——原型模式

概念:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

解释说明:
1.从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
2.在实例化的构造函数执行时间很长,并且初始化的信息不发生变化的情况下,使用克隆技术,
3.不用重新初始化对象,而是动态地获得对象运行时的状态。
4.我们只需要实现ICloneable接口就可以。该接口只有一个Clone()方法。

原型模式结构类图:


个人总结的基本用法:
想要对次创建谁,那谁就是原型,在原型类当中定于原型的属性,方法,最主要的是Clone方法啦,用于创建当前对象的副本,把当前对象的字段复制给新对象,如果字段的值是值类型,则逐位复制,如果是引用类型,则只复制引用,即只复制地址,新对象和被复制的对象指向同一个空间地址。在客户端调用Clone方法


MemberwiseClone()方法中,如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型的,则只复制引用但不复制引用的对象。

浅复制
实例代码:
工作经历类两个属性。
//工作经历类,定义类的两个属性  
    class WorkExperience
    {
        private string workDate;
        public string WorkDate
        {
            get { return workDate;}
            set {workDate =value; }
        }
        private string company;
        public string Company
        {
            get { return company; }
            set { company = value;}
        }
    }

简历类当中有设置工作经历的方法,简历类直接调用“工作经历”这个方法就可以。
//简历
    class Resume:ICloneable 
    {
        private string ame;
        private string sex;
        private string age;

        //引用工作经历对象
        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 void Display()
        {
            //实现接口的方法,用来克隆对象
            Console.WriteLine("{0} {1} {2}", name);
            Console.WriteLine("工作经历:{0} {1}", work.WorkDate , work.Company);
        }

        public object Clone()
        {
            return (Object)this.MemberwiseClone();
        }
    }

b和c都克隆了a,当执行了Resume b=(Resume)a.Clone();的时候,由于work对象是引用类型的,所以a就把引用传给了b,这样他们指向相同work对象的空间地址。
 static void Main(string[] args)
        {
            Resume a = new Resume("大鸟");
            a.SetWorkExperience("1998-2000","脸型公司");

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

            Resume c = (Resume)a.Clone();
            c.SetWorkExperience("1998-2003", "zz企业");

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

            Console.Read();
        }

个人理解:
在原型类中引用了另一个类的对象,同时定义了Clone方法,用于创建本身的副本,在客户端调用Clone方法,但是由于字段是引用类型的,于是就把引用复制了,这样克隆出来的对象和前面的对象指向同一个地址空间。

深复制:
实例代码:
让“工作经历”实现克隆方法。
//工作经历类,定义类的两个属性 
    //让工作经历类实现IConeable接口

    class WorkExperience
    {
        private string workDate;
        public string WorkDate
        {
            get { return workDate;}
            set {workDate =value; }
        }
        private string company;
        public string Company
        {
            get { return company; }
            set { company = value;}
        }
        //工作经历类实现克隆方法
        public Object Clone()
        {
            return (Object)this.MemberwiseClone();
        }
     }

在简历类当中定义一个构造函数,用于克隆“工作经历”的数据
//简历
    class Resume:ICloneable 
    {
        private string name;
        private string sex;
        private string age;

        //引用工作经历对象
        private WorkExperience work;

        //在“简历”类实例化时同时实例化“工作经历”
        public Resume(string name)
        {
            this.name = name;
            work = new WorkExperience();
        }

        //提供Clone方法调用的私有构造函数,以便克隆工作经历的数据
        private Resume(WorkExperience work)
        {
            this.work = (WorkExperience)work.Clone();
        }
        //设置个人信息
        public void SetPersonalInfo(string sex, string age)
        {
            this.sex = sex;
            this.age = age;
        }

        //设置工作经历
        public void SetWorkExperience(string workDate, string company)
        {
            work.WorkDate  = workDate ;
            work.Company  = company;
        }

        //显示
        public void Display()
        {
            //实现接口的方法,用来克隆对象
            Console.WriteLine("{0} {1} {2}", name, sex, age);
            Console.WriteLine("工作经历:{0} {1}", work.WorkDate , work.Company);
        }
      
        public object Clone()
        {
            Resume obj = new Resume(this.work);  //调用私有的构造方法,让“工作经历”克隆完成
            obj.name = this.name;
            obj.sex = this.sex;
            obj.age = this.age;
            return obj;
        }
    }

浅复制与深复制的区别?
浅复制没有克隆被引用对象中的数据,只是传了引用。深复制在被引用对象中定义了克隆的方法,用于克隆其中的数据。

下面是我总结的原型模式的由来及之间的关系图:

在原来的方法,我们复制简历的时候,需要实例化多份简历对象,这样就需要多次执行简历类中定义的构造函数,如果每次执行构造函数的时间非常长的话,就会浪费很多的时间,效率会很低。如何改进这种情况呢?那就是尽量避免实例化每一份简历,我们只需要创建第一份简历就行,然后克隆他就可以得到我们想要的其他的简历。

浅复制:
但是当简历中的字段是值类型的时候可以复制过去,但当字段是引用类型的时候我们只是复制了引用,所以每次复制都指向相同的空间,导致所有的引用都是最后一次设置,这就是浅复制。如何解决这个问题呢?那就是深复制:

深复制:
深复制在被引用对象中定义了克隆的方法,用于克隆其中的数据









评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诗琪小姐姐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值