• 原型模式


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

      简单说来原型模式就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。

      原型模式UML图:

        

      原型模式的基本代码结构:

    namespace ConsoleApplication1
    {
        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();   //创建当前对象的浅表副本。方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。
                                                            //如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象
                                                            //因此,原始对象及其副本引用同意对象
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                ConcretePrototype1 p1 = new ConcretePrototype1("I");
                ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();     //原型模式创建对象
                Console.WriteLine("Cloned:{0}",c1.Id);  //输出 Cloned:I
    
                Console.ReadKey();
            }
        }  
    }

      原型模式的作用:我们知道每new一次对象,都需要执行一次构造函数,如果构造函数的执行时间很长,那么多次的执行初始化操作就比较低效。一半在初始化的信息不发生变化的情况下,克隆是最好的办法,这既隐藏了对象创建的细节,又能对性能是大大的提高。不用重新初始化对象,而是动态地获得对象运行时的状态。

      在使用原型模式中,有必要注意浅复制与深复制的概念。

      对于上面的原型结构示例代码:我们知道如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型的,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同意对象。

      浅复制:被复制对象的所有变量都含有与原来对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。也就是说,浅复制复制出来的对象,如果里面含有引用类型的数据,则浅复制复制出来的对象与原对象是同一个,因为仅复制引用地址嘛。

      深复制:当执行复制时,被复制的对象含有引用类型对象的变量时,引用类型的变量对象也重新复制一份,即复制出来的引用对象与原类中的对象不是指向同一个地址。

      因此,在使用原型模式时必须要分析好,是该浅复制还是深复制。

      回到《大话设计模式中的示例》 简历的原型实现:

    namespace ConsoleApplication1
    {
        class WorkExperience : 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 WorkExperience work;
    
            public Resume(string Name)
            {
                this.name = Name;
                work = new WorkExperience();
            }
    
            private Resume(WorkExperience Work)
            {
                this.work = (WorkExperience)Work.Clone();   //注意深复制必须要添加此段代码,提供Clone方法调用的私有构造函数以便克制工作经历
            }
    
            //设置个人信息
            public void SetPersonnalInfo(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;
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Resume a = new Resume("大鸟");
                a.SetPersonnalInfo("","29");
                a.SetWorkExperience("1998-2000","微软");
    
                Resume b = (Resume)a.Clone();
                b.SetWorkExperience("2000-2004","google");
    
                Resume c = (Resume)a.Clone();
                c.SetPersonnalInfo("","24");
                c.SetWorkExperience("1998-2004","苹果");
    
                a.Display();
                b.Display();
                c.Display();
    
                Console.ReadKey();
            }
        }  
    }

      

  • 相关阅读:
    LeetCode-62. Unique Paths
    南大算法设计与分析课程课后习题(3)
    linux-2.6.18源码分析笔记---信号
    南大算法设计与分析课程复习笔记(4)L4
    南大算法设计与分析课程复习笔记(3)L3
    南大算法设计与分析课程复习笔记(2)L2
    南大算法设计与分析课程OJ答案代码(2)最大子序列和问题、所有的逆序对
    【zz】史上最全设计模式导学目录(完整版)
    gtest学习
    全文检索及ElasticSearch框架学习
  • 原文地址:https://www.cnblogs.com/qixuejia/p/4512079.html
Copyright © 2020-2023  润新知