C军

不玩博客了!

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

  原型模式(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();
        }
    }  
}

  

posted on 2013-03-17 21:41  逆心  阅读(745)  评论(0编辑  收藏  举报