设计模式之---原型模式

原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式其实就是从一个对象(而不是通过类的实例化)再创建另一个可定制的对象,而且不需要知道任何创建的细节。

一般在初始化的信息不发生变化的情况下,克隆是最好的办法,这既隐藏了对象创建的细节,又对性能是很大的提升

基本代码:

abstract class Prototype//原型类
    {
        private string id;
        public Prototype(string id)
        {
            this.id = id;
        }
        public string Id
        {
            get
            {
                return id;
            }
        }
        public abstract Prototype Clone();
    }
    class ConcretePrototype1:Prototype//具体原型类
    {
        public ConcretePrototype1(string id):base(id)
        {

        }
        public override Prototype Clone()
        {
            return (Prototype)this.MemberwiseClone();
            //创建当前对象的浅表副本。方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型
            //则复制引用但不复制引用的对象;因此原始对象及其副本引用同一对象【即引用的对象数据是不会被克隆过来的】
        }
    }
View Code
        static void Main(string[] args)
        {
            

            //浅复制
            ConcretePrototype1 p1 = new ConcretePrototype1("I");
            ConcretePrototype1 C1=(ConcretePrototype1)p1.Clone();
            Console.WriteLine("Cloned:{0}" ,C1.Id);
            Console.Read();
        }     
View Code

注意以上MemberWiseClone()方法创建当前对象的浅表副本。方法是创建一个新对象,然后当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不会复制引用的对象,因此原始对象及其副本引用同一对象

例如如下案例:就介绍了浅拷贝的特点,克隆通过ICloneable接口实现。

用途:一般在初始化的信息不发生变化的情况下,克隆是最好的办法,这即隐藏了对象创建的细节,又对性能是大大的提升。

客户端

        static void Main(string[] args)
        {

            Resume a = new Resume("我是谁");
            a.SetPersonalInfo("", "29");
            a.SetWorkExperience("2018-11-1", "杭州德川");

            Resume b = (Resume)a.Clone();
            b.SetWorkExperience("2020-2-09", "dahua");
            Resume c = (Resume)a.Clone();
            c.SetPersonalInfo("", "23");
            c.SetWorkExperience("2021-9-08", "kaba");
            a.Display();
            b.Display();
            c.Display();
           
            Console.Read();
        } 
View Code
    class WorkExperience
    {
        public string WorkData { get; set; }
        public string Company { get; set; }
    }
    class Resume : ICloneable
    {
        private string name;
        private string sex;
        private string age;
        private WorkExperience work;
        public Resume(string name)
        {
            this.name = name;
            this.work = new WorkExperience();
        }
        public void SetPersonalInfo(string sex,string age)
        {
            this.sex = sex;
            this.age = age;
        }
        public void SetWorkExperience(string workData,string company)
        {
            work.Company = company;
            work.WorkData = workData;
        }
        public void Display()
        {
            Console.WriteLine("{0},{1},{2}", name, sex, age);
            Console.WriteLine("工作经历:{0},{1}", work.WorkData, work.Company);
        }
        public object Clone()
        {
            return (object)this.MemberwiseClone();
        }
    }
View Code

最后会发现输出的都是“工作经历 2021-9-08 kaba"。这就是浅拷贝。

为了解决这个问题需要把复制的对象所引用的对象都复制一遍,这就是深拷贝。

代码修改如下:

    class WorkExperience:ICloneable
    {
        public string WorkData { get; set; }
        public string Company { get; set; }

        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;
            this.work = new WorkExperience();
        }
        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 workData,string company)
        {
            work.Company = company;
            work.WorkData = workData;
        }
        public void Display()
        {
            Console.WriteLine("{0},{1},{2}", name, sex, age);
            Console.WriteLine("工作经历:{0},{1}", work.WorkData, 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;
        }
    }
View Code

 

posted @ 2021-10-04 22:44  HelloWorld庄先生  阅读(26)  评论(0编辑  收藏  举报