设计模式-创建型模式:原型模式PrototypeModel

原型模式:不重复调用构造函数,在不通过构造函数的情况下,创建一个对象出来

通过克隆的方式创建对象,让整个程序使用的是不同的对象

应用案例:Sql局部更新

原型模式分为 浅表克隆和深表克隆


浅表克隆代码:

Lol类:

 class Lol
    {
         private Lol()
         {
             Console.WriteLine("构造函数 执行一次");
         }

         private static Lol loler = null;

         static Lol()
         {
             loler = new Lol();
         }
         public string Name { get; set; }
         public static Lol CreateInstance()
         {
             Lol lolers = (Lol)loler.MemberwiseClone();//克隆一个新的对象
             return lolers;
         }
    }
调用

Lol loler1 = Lol.CreateInstance();
            loler1.Name = "发条魔灵";
            Lol loler2 = Lol.CreateInstance();
            loler2.Name = "锤石";
            Console.WriteLine("第一英雄是{0}********第二个英雄是{1}",loler1.Name,loler2.Name);

            Console.Read();
结果:



但是 这种克隆方式  是有缺陷的,如下所示:

添加以下代码:

添加一个类 表示英雄信息

 public class Xx
    {
       public int ID { get; set; }
       public string Xb { get; set; }
    }

修改以前的Lol类

 class Lol
    {
         private Lol()
         {
             Console.WriteLine("构造函数 执行一次");
         }

         private static Lol loler = null;

         static Lol()
         {
             loler = new Lol();
             loler.Xxs = new Xx()
             {
                 ID = 3,
                 Xb = "不男不女"
             };
         }
         public string Name { get; set; }
         public Xx Xxs { get; set; }
         public static Lol CreateInstance()
         {
             Lol lolers = (Lol)loler.MemberwiseClone();//克隆一个新的对象
             return lolers;
         }

       
    }

调用

Lol loler1 = Lol.CreateInstance();
            loler1.Name = "发条魔灵";
            Lol loler2 = Lol.CreateInstance();
            loler2.Name = "锤石";
            Console.WriteLine("第一英雄是{0}********第二个英雄是{1}",loler1.Name,loler2.Name);

            Console.WriteLine("**********************原型模式 浅表克隆缺点***************************");
            loler1.Xxs.ID = 1;
            loler1.Xxs.Xb = "女";
            Console.WriteLine("{0}的ID是{1}、性别是{2}",loler1.Name,loler1.Xxs.ID,loler1.Xxs.Xb);
            Console.WriteLine("下面给loler2的Xxs赋值");
            loler2.Xxs.ID = 2;
            loler2.Xxs.Xb = "男";
            Console.WriteLine("{0}的ID是{1}、性别是{2}", loler2.Name, loler2.Xxs.ID, loler2.Xxs.Xb);
            Console.WriteLine("再看一下 修改完loler2后的loler1中Xxs的值");
            Console.WriteLine("{0}的ID是{1}、性别是{2}", loler1.Name, loler1.Xxs.ID, loler1.Xxs.Xb);


            Console.Read();

执行结果


第二次给Xxs里面内容赋值后,会影响到1里面的 内容,因为Xxs是一个引用类型,指向的是一块内存空间,所以修改之后,1和2都会一起修改


为了解决上述问题 通过序列化推出 深表克隆

通过对克隆出来的对象进行序列化后再反序列化 会得到一个全新的对象

前提记得给需要序列化的加特性修饰 [Serializable]


新增序列化方法

public class SerialzeHelper
    {
        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        public static string Serializable(object target)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                new BinaryFormatter().Serialize(stream,target);
                return Convert.ToBase64String(stream.ToArray());
            }
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="target"></param>
        /// <returns></returns>
        public static T Derializable<T>(string target)
        {
            byte[] targetArray = Convert.FromBase64String(target);
            using(MemoryStream stream = new MemoryStream(targetArray))
            {
                return (T)(new BinaryFormatter().Deserialize(stream));
            }
        }
    }
方法添加 [Serializable]修饰

调用:

 static void Main(string[] args)
        {
            Lol loler1 = Lol.CreateInstance();
            loler1.Name = "发条魔灵";
            Lol loler2 = Lol.CreateInstance();
            loler2.Name = "锤石";
            Console.WriteLine("第一英雄是{0}********第二个英雄是{1}",loler1.Name,loler2.Name);

            Console.WriteLine("**********************原型模式 浅表克隆缺点***************************");
            loler1.Xxs.ID = 1;
            loler1.Xxs.Xb = "女";
            Console.WriteLine("{0}的ID是{1}、性别是{2}",loler1.Name,loler1.Xxs.ID,loler1.Xxs.Xb);
            Console.WriteLine("下面给loler2的Xxs赋值");
            loler2.Xxs.ID = 2;
            loler2.Xxs.Xb = "男";
            Console.WriteLine("{0}的ID是{1}、性别是{2}", loler2.Name, loler2.Xxs.ID, loler2.Xxs.Xb);
            Console.WriteLine("再看一下 修改完loler2后的loler1中Xxs的值");
            Console.WriteLine("{0}的ID是{1}、性别是{2}", loler1.Name, loler1.Xxs.ID, loler1.Xxs.Xb);
            Console.WriteLine("**********************深表克隆***************************");
            Lol loler3 = SerialzeHelper.Derializable<Lol>(SerialzeHelper.Serializable(loler2));
            Console.WriteLine("下面修改loler3的值");
            loler3.Xxs.ID = 99;
            loler3.Xxs.Xb = "很奇怪";
            Console.WriteLine("{0}的ID是{1}、性别是{2}", loler1.Name, loler1.Xxs.ID, loler1.Xxs.Xb);
            Console.WriteLine("{0}的ID是{1}、性别是{2}", loler2.Name, loler2.Xxs.ID, loler2.Xxs.Xb);
            Console.WriteLine("{0}的ID是{1}、性别是{2}", loler3.Name, loler3.Xxs.ID, loler3.Xxs.Xb);
            Console.Read();
        }

结果:



最后3的修改 并没有影响1和2的值

个人学习笔记 可添加我QQ 1219958536  共同探讨 加好友的时候记得备注CSDN


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值