设计模式-原型模式

原型模式

用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。从一个对象再创建一个可定制的对象,而且不需知道任何创建的细节。

Memberwiseclone()方法

如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型的,则复制引用但不复制引用的对象。形成原始对象与其复本引用同一对象。简单来说,值类型变量,无论是浅复制还是深复制,其值会因原始对象的更改而更改。引用类型变量,若是浅复制,其克隆对象的值会随原始对象的变化而变化。若是深复制,其克隆对象的值不会随原始对象的变化而变化。

代码解释

有一个类。实例化复制后想保留这个实例的一个备份。
例如 :
//Clone类中包含一个int length字段。
Clone cloneTest=new Clone();
Clone cloneCopy=newClone();
cloneTest..length=0;
cloneCopy=cloneTest;
到这个部分cloneTestcloneCopy中的length值都变为0了。 但如果接着加一行代码cloneTest.length=1;
预期是希望cloneTestlength=1cloneCopylength=0;但实际两者都变为1了。

这里出现这个原因就是因为类是个引用类型,所以当执行cloneCopy=cloneTest;时,是将地址给过去了。于是当然一者变。两者都会变了。c#中的引用类型采用这种方法都是给地址。复制引用地址就是浅度复制。而复制对象的值,创建新的对象就是深度复制。

模式代码解释

一、浅复制

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 name;
        private string sex;
        private string age;

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

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

        public void SetPersonaInfo(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()
        {
            return (object)this.MemberwiseClone();
        }
    }

客户端代码:

 static void Main(string[] args)
        {
            Resume a = new Resume("大年");
            a.SetPersonaInfo("男", "29");
            a.SetWorkExperience("1998-2000", "XX公司");

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

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

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

            Console.Read();
        }

二、深复制

 class WorkExperienct : ICloneable//工作经历实现ICloneable接口
    {
        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 WorkExperienct work;

        public Resume(string name)
        {
            this.name = name;
            work = new WorkExperienct();
        }

        private Resume(WorkExperienct work)
        //提供Clone方法调用的私有构造函数,以便克隆工作经历的数据
        {
            this.work = (WorkExperienct)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;
        }
    }

优点:

1.性能提高

2.逃避构造函数的约束

缺点:

1.配备克隆方法需要对类的功能进行通盘考虑,对于全新的类不是很难,当对于已有的类,应用不支持串行化的间接对象,或引用含有循环结构时,比较复杂

2.必须实现cloneable接口

使用场景:

1、资源优化场景。 
2、类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。 
3、通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。 
4、一个对象多个修改者的场景。一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。 

5、在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值