原型模式:值类型和引用类型的深拷贝与浅拷贝

1.拷贝对象

namespace Data
{
    /// <summary>
    /// 要被浅拷贝的对象
    /// </summary>
    public abstract class Prototype
    {
        public string ID { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public DegreeInfo DegreeInfo;

        public Prototype(string id)
        {
            ID = id;
        }

        public void SetInfo(string name, string address)
        {
            Name = name;
            Address = address;
        }

        /// <summary>
        /// 返回本类的一个对象
        /// </summary>
        /// <returns></returns>
        public abstract Prototype Clone();
    }

    public class PrototypeEx : Prototype
    {
        /// <summary>
        /// 必须要有这个方法
        /// </summary>
        /// <param name="id"></param>
        public PrototypeEx(string id)
            : base(id)
        { }

        /// <summary>
        /// 创建一个对象的浅表副本。创建一个新对象,将当前对象的非静态字段复制到新对象。如果
        /// 字段的类型是值类型,则对该字段进行逐位复制;若是引用类型,则复制引用,不复制对象。
        /// 因此,原始对象和副本引用同一对象.
        /// </summary>
        /// <returns></returns>
        public override Prototype Clone()
        {
            return (Prototype)this.MemberwiseClone();//这里要强转
        }
    }

    /// <summary>
    /// 学历信息
    /// </summary>
    public class DegreeInfo
    {
        public string DegreeID { get; set; }
        public string DegreeName;
        public string University { get; set; }
        public DegreeInfo(string id,string universityName)
        {
            DegreeID = id;
            University = universityName;
        }
    }

    /// <summary>
    /// 要被拷贝的对象;进行深拷贝
    /// </summary>
    public class PrototypeExx : ICloneable
    {
        public string ID { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public DegreeInfoEx DegreeInfo;

        public PrototypeExx()
        {
        }

        public PrototypeExx(string id)
        {
            ID = id;
        }

        public void SetInfo(string name, string address)
        {
            Name = name;
            Address = address;
        }

        /// <summary>
        /// 进行一次深拷贝
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            PrototypeExx obj = new PrototypeExx();
            obj.ID = this.ID;
            obj.Name = this.Name;
            obj.Address = Address;
            obj.DegreeInfo = (DegreeInfoEx)this.DegreeInfo.Clone();
            return obj;
        }
    }

    /// <summary>
    /// 学历信息;进行深拷贝
    /// </summary>
    public class DegreeInfoEx : ICloneable
    {
        public string DegreeID { get; set; }
        public string DegreeName;
        public string University { get; set; }
        public DegreeInfoEx(string id, string universityName)
        {
            DegreeID = id;
            University = universityName;
        }

        #region ICloneable 成员

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

        #endregion
    }
}

2.调用

static void Main(string[] args)
        {
            /*原型模式:使用MemberwiseClone方法对数据进行浅表拷贝;实现ICloneable接口进行深拷贝
             * 从下面的实例看出:
             * 1和2对比,当修改p1后,p2对应的数据没有变化,意味着p2是p1对象中非引用类型数据(包括string类型)的独立拷贝。
             * 1和3对比,当修改p1中DegreeInfo类的信息后,p2的信息跟着变化,意味着p1,p2的DegreeInfo数据是引用的同一个对象
             *
             * 深拷贝能解决上面出现的问题,拷贝一份全新的对象
             *
             * 两种拷贝方式其实都是调用了同一个方法:MemberwiseClone。深拷贝不同之处在于实现了ICloneable接口。内部类的拷
             * 贝还是属于浅拷贝
             * */

            Console.WriteLine("浅拷贝实例");
            DegreeInfo info = new DegreeInfo("110344", "四川师范");
            info.DegreeName = "本科";
            PrototypeEx p1 = new PrototypeEx("344");
            p1.SetInfo("yoyo1", "成都");
            p1.DegreeInfo = info;
            PrototypeEx p2 = (PrototypeEx)p1.Clone();
            Console.WriteLine("1.  {0},{1},{2},{3},{4},{5}",p2.ID,p2.Name,p2.Address,p2.DegreeInfo.DegreeID,p2.DegreeInfo.University,p2.DegreeInfo.DegreeName);
            //修改p1对象信息
            p1.SetInfo("yoyo3","北京");
            Console.WriteLine("2.  {0},{1},{2},{3},{4},{5}", p2.ID, p2.Name, p2.Address, p2.DegreeInfo.DegreeID, p2.DegreeInfo.University, p2.DegreeInfo.DegreeName);
            //info.DegreeName = "专科";
            p1.DegreeInfo.DegreeName = "专科";
            Console.WriteLine("3.  {0},{1},{2},{3},{4},{5}", p2.ID, p2.Name, p2.Address, p2.DegreeInfo.DegreeID, p2.DegreeInfo.University, p2.DegreeInfo.DegreeName);

            Console.WriteLine("深拷贝实例");
            DegreeInfoEx infoCQ = new DegreeInfoEx("110355", "重庆师范");
            infoCQ.DegreeName = "本科";
            PrototypeExx p3 = new PrototypeExx("355");
            p3.SetInfo("yoyo2","重庆");
            p3.DegreeInfo = infoCQ;
            PrototypeExx p4 = (PrototypeExx)p3.Clone(); ;
            Console.WriteLine("1.  {0},{1},{2},{3},{4},{5}", p4.ID, p4.Name, p4.Address, p4.DegreeInfo.DegreeID, p4.DegreeInfo.University,p4.DegreeInfo.DegreeName);
            p3.SetInfo("yoyo4", "昆明");
            Console.WriteLine("2.  {0},{1},{2},{3},{4},{5}", p4.ID, p4.Name, p4.Address, p4.DegreeInfo.DegreeID, p4.DegreeInfo.University, p4.DegreeInfo.DegreeName);
            //修改p3
            infoCQ.DegreeName = "专科";
            Console.WriteLine("3.  {0},{1},{2},{3},{4},{5}", p4.ID, p4.Name, p4.Address, p4.DegreeInfo.DegreeID, p4.DegreeInfo.University, p4.DegreeInfo.DegreeName);
            Console.ReadKey();
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值