原型模式(Prototype Pattern)

   

原型模式(Prototype Pattern):
用原型实例创建指定的对象的种类,并且通过拷贝这些原型创建新的对象。
Prototype:原型类,声明一个克隆自身的接口。
ConcretePrototype:具体的原型类,继承Prototype,实现一个克隆自身的操作。
Clinet:让一个原型克隆自身从而创建一个新的对象。
原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
原型模式代码:
原型类(Prototype):
abstract class Prototype
    {
        private string id;
        public Prototype(string id)
        {
            this.id = id;
        }
        public string Id
        {
            get { return id; }
        }

        //抽象类关键是具有这样一个Clone方法
        public abstract Prototype Clone();

    }

具体原型类(ConcretePrototype):
class ConcretePrototype : Prototype
    {
        public ConcretePrototype(string id)
            : base(id)
        {
        }

        //创建当前对象的浅表副本。方法是创建一个新对象,然后讲当前对象的非
        //静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制
        //如果字段是引用类型,则复制引用但不复制引用的对象,因此,原始对象及
        //副本引用同一对象
        public override Prototype Clone()
        {
            return (Prototype)this.MemberwiseClone();
        }
    }

客户端代码:
ConcretePrototype p1=new ConcretePrototype("I");
//克隆类ConcretePrototype的对象p1就能得到新的实例c1
ConcretePrototype c1=(ConcretePrototype)p1.Clone();
Console.WtiteLine("Cloned:{0}",c1.id);

说明:.Net在System命名空间中提供了ICloneable接口,其中就是唯一的一个方法Clone(),所以
只要实现这个接口就可以完成原型模式了

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

浅表复制(Shallow Copy)和深层复制(Deep Copy):MemberwiseClone()方法是如果字段是值类型的,则对该字段执行逐位复制;如果字段是
引用类型,则复制引用但不复制引用的对象;进许浅表复制时,如果父类包含的子引用对象发生变化,这个变化同时也出现在它的浅表
复制的克隆对象中;深层复制中,如果父类对象发生改变,这个变化不会出现在它的深层复制的克隆对象中。

实例
1:简历的原型模式实现

 

public class Resume : ICloneable
    {
        private string _name;
        private string _sex;
        private int _age;
        private string _timeArea;
        private string _company;

        public Resume(string name)
        {
            this._name = name;
        }

        //设置个人信息
        public void SetPersonalInfo(string sex, int age)
        {
            this._sex = sex;
            this._age = age;
        }

        //设置工作经历
        public void SetWorkExperience(string timeArea, string company)
        {
            this._timeArea = timeArea;
            this._company = company;
        }

        //显示简历
        public void Display()
        {
            Console.WriteLine("{0} {1} {2}", _name, _sex, _age.ToString());
            Console.WriteLine("工作经历:{0} {1}", _timeArea, _company);
        }

       


        #region ICloneable 成员
        //自身克隆方法
        public object Clone()
        {
            //浅表复制
            return (Object)this.MemberwiseClone();
        }

        #endregion
    }

 

//原型模式(值类型克隆)
            Resume a = new Resume("埃里克斯");
            a.SetPersonalInfo("男", 25);
            a.SetWorkExperience("2009-2010", "XX公司");
           
            //只需要调用Clone方法就可以实现新简历的生成,并且可以再修改新简历的细节
            Resume b = (Resume)a.Clone();
            b.SetWorkExperience("2010-2011", "YY公司");
           
            Resume c = (Resume)a.Clone();
            c.SetPersonalInfo("女", 24);

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

 

输出结果:

埃里克斯 男 25

2009-2010 XX公司

埃里克斯 男 25

2010-2011 YY公司

埃里克斯 女 24

2009-2010 XX公司

 

如果此时工作经历是一个单独的类,如下

/// <summary>
    /// 工作经历类
    /// </summary>
    public 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; }
        }
    }

 

/// <summary>
    /// 简历类,深层复制
    /// </summary>
    public class Resume2:ICloneable
    {
        private string _name;
        private string _sex;
        private int _age;

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

        public Resume2(string name)
        {
            this._name = name;
            work = new WorkExperience();
        }

        //设置个人信息
        public void SetPersonalInfo(string sex, int age)
        {
            this._sex = sex;
            this._age = age;
        }

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

        //显示简历
        public void Display()
        {
            Console.WriteLine("{0} {1} {2}", _name, _sex, _age.ToString());
            Console.WriteLine("工作经历:{0} {1}", work.WorkDate, work.Company);
        }

        #region ICloneable 成员

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

        #endregion
    }

 

//原型模式(引用类型克隆)
            Resume2 a2 = new Resume2("迈克");
            a2.SetPersonalInfo("男", 26);
            a2.SetWorkExperience("2009-2010", "XX公司");
           
            Resume2 b2 = (Resume2)a2.Clone();
            b2.SetWorkExperience("2010-2011", "YY公司");
           
            Resume2 c2 = (Resume2)a2.Clone();
            c2.SetPersonalInfo("男", 22);
            c2.SetWorkExperience("2011-2012", "ZZ公司");

            //显示结果都是最后一次设置的值
            a2.Display();
            b2.Display();
            c2.Display();

 

显示结果:

迈克 男 26

2011-2012 ZZ公司

迈克 男 26

2011-2012 ZZ公司

迈克 男 22

2011-2012 ZZ公司

 

工作经历显示的都是最后设置的值

 

让工作经历类也继承ICloneable接口,实现自身的克隆

/// <summary>
    /// 工作经历类:继承ICloneable接口
    /// </summary>
    public class WorkExperience2: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; }
        }


        #region ICloneable 成员
        //克隆自身方法
        public object Clone()
        {
            return (Object)this.MemberwiseClone();
        }

        #endregion
    }

/// <summary>
    /// 深层复制
    /// </summary>
    public class Resume3:ICloneable
    {
        private string _name;
        private string _sex;
        private int _age;

        //引用“工作经历”对象
        private WorkExperience2 _work;

        public Resume3(string name)
        {
            this._name = name;
            _work = new WorkExperience2();
        }

        //提供Clone方法调用的私有构造函数,以便克隆“工作经历”的数据
        public Resume3(WorkExperience2 work)
        {
            this._work = (WorkExperience2)work.Clone();
        }

        //设置个人信息
        public void SetPersonalInfo(string sex, int age)
        {
            this._sex = sex;
            this._age = age;
        }

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

        //显示简历
        public void Display()
        {
            Console.WriteLine("{0} {1} {2}", _name, _sex, _age.ToString());
            Console.WriteLine("工作经历:{0} {1}", _work.WorkDate, _work.Company);
        }

        #region ICloneable 成员

        public object Clone()
        {
            //调用私有的构造函数,让“工作经历”克隆完成,然后再给这个“简历”
            //对象的相关字段赋值,最终返回一个深复制的简历对象
            Resume3 obj = new Resume3(this._work);
            obj._name = this._name;
            obj._sex = this._sex;
            obj._age = this._age;
            return obj;
        }

        #endregion

 

//原型模式(引用类型深层复制克隆)
            Resume3 a3 = new Resume3("迈克");
            a3.SetPersonalInfo("男", 26);
            a3.SetWorkExperience("2009-2010", "XX公司");

            Resume3 b3 = (Resume3)a3.Clone();
            b3.SetWorkExperience("2010-2011", "YY公司");

            Resume3 c3 = (Resume3)a3.Clone();
            c3.SetPersonalInfo("男", 22);
            c3.SetWorkExperience("2011-2012", "ZZ公司");

            a3.Display();
            b3.Display();
            c3.Display();

 

显示结果:

迈克 男 26

2009-2010 XX公司

迈克 男 26

2010-2011 YY公司

迈克 男 22

2011-2012 ZZ公司

 

 

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值