原型模式:不重复调用构造函数,在不通过构造函数的情况下,创建一个对象出来
通过克隆的方式创建对象,让整个程序使用的是不同的对象
应用案例: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