用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
工作原理:将一个原型对象传给要发动创建的对象(即客户端对象),这个要发动创建的对象通过请求原型对象复制自己来实现创建过程
创建新对象(也称为克隆对象)的工厂就是原型类自身,工厂方法由负责复制原型对象的克隆方法来实现
通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址,每一个克隆对象都是独立的
通过不同的方式对克隆对象进行修改以后,可以得到一系列相似但不完全相同的对象
- 当一个系统独立于它的产品创建,构成和表示时,要使用原型模式。
- 当要实例化的类是在运行时刻指定的,例如通过动态装载。
- 为了避免创建一个与产品类层次平行的工厂类层次。
- 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们,可能比每次用合适的状态手工实例化方便些
Prototype 声明一个克隆自身的接口
ConcretePrototype 实现一个克隆自身的操作
Client 让一个原型克隆自身从而创建新的对象
浅克隆与深克隆
浅克隆(Shallow Clone):当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制
深克隆(Deep Clone):除了对象本身被复制外,对象所包含的所有成员变量也将被复制
浅度复制(Shallow Copy):将原来对象中的所有字段逐个复制到一个新对象,如果字段是值类型,则简单地复制一个副本到新对象,改变新对象的值类型字段不会影响原对象;如果字段是引用类型,则复制的是引用,改变目标对象中引用类型字段的值将会影响原对象。
深度复制(Deep Copy):与浅复制不同之处在于对引用类型的处理,深复制将新对象中引用类型字段指向复制过的新对象,改变新对象中引用的任何对象,不会影响到原来的对象中对应字段的内容。
.浅度复制
先看原型模式的经典实现:定义一个接口, 用来表述所有的颜色对象接口
1 /// <summary> 2 /// 颜色接口 3 /// </summary> 4 public interface IColor 5 { 6 IColor Clone(); 7 8 int Red { get; set; } 9 int Green { get; set; } 10 int Blue { get; set; } 11 }
给出红色的具体实现代码:
1 public class RedColor:IColor 2 { 3 public int Red { get; set; } 4 public int Green { get; set; } 5 public int Blue { get; set; } 6 7 public IColor Clone() 8 { 9 return (IColor)this.MemberwiseClone(); 10 } 11 }
测试代码
1 static void Main(string[] args) 2 { 3 IColor color = new RedColor(); 4 color.Red = 255; 5 Console.WriteLine("color -red " + color.Red); //225 6 IColor color1 = color.Clone(); 7 color1.Red = 224; 8 Console.WriteLine("color1-red " + color1.Red);//224 9 Console.WriteLine("color -red " + color.Red); //225 10 }
二.深度复制:
深复制考虑的情况相对来说就会比较复杂,因为有可能对象是之间有继承关系或者引用关系的时候,可能我们深复制的时候就需要注意.
一般来说深复制一方面可以采用种简单的深复制对象的时候的方案,还可以通过序列化的形式来进行对象的复制。
下面通过序列化的形式来实现原型模式:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleApplication4 7 { 8 /// <summary> 9 /// 颜色接口 10 /// </summary> 11 public interface IColor 12 { 13 IColorDemo Clone(); 14 15 int Red { get; set; } 16 int Green { get; set; } 17 int Blue { get; set; } 18 Factroy f{get;set;} 19 } 20 21 /// <summary> 22 /// 生产颜色的工厂信息 23 /// </summary> 24 [Serializable] 25 public class Factroy 26 { 27 public string name { get; set; } 28 } 29 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleApplication4 7 { 8 /// <summary> 9 /// 颜色 10 /// </summary> 11 [Serializable] 12 public class RedColor:IColor 13 { 14 public int Red { get; set; } 15 public int Green { get; set; } 16 public int Blue { get; set; } 17 public Factroy f { get; set; } 18 19 public IColor Clone() 20 { 21 SerializableHelper s = new SerializableHelper(); 22 string target = s.Serializable(this); 23 return s.Derializable<IColor>(target); 24 } 25 } 26 }
1 /// <summary> 2 /// 序列化和反序列化辅助类 3 /// </summary> 4 public class SerializableHelper 5 { 6 public string Serializable(object target) 7 { 8 using (MemoryStream stream = new MemoryStream()) 9 { 10 new BinaryFormatter().Serialize(stream, target); 11 12 return Convert.ToBase64String(stream.ToArray()); 13 } 14 } 15 16 public object Derializable(string target) 17 { 18 byte[] targetArray = Convert.FromBase64String(target); 19 20 using (MemoryStream stream = new MemoryStream(targetArray)) 21 { 22 return new BinaryFormatter().Deserialize(stream); 23 } 24 } 25 26 public T Derializable<T>(string target) 27 { 28 return (T)Derializable(target); 29 } 30 }
1 static void Main(string[] args) 2 { 3 IColor color = new RedColor(); 4 color.Red = 255; 5 color.f = new Factroy() { name="湖北工厂" }; 6 Console.WriteLine("color - Factroy:" + color.f.name); //湖北工厂 7 8 IColor color1 = color.Clone(); 9 color1.Red = 234; 10 color1.f.name = "北京工厂"; 11 Console.WriteLine("color1- Factroy:" + color1.f.name); //北京工厂 12 Console.WriteLine("color - Factroy:" + color.f.name); //湖北工厂 13 Console.Read(); 14 }
结论:通过序列化和反序列化形成新的对象。其实只要是项目中要使用原型模式进行对象复制的情况下,都可以通过序列化的形式来进行深复制。
学习于 https://blog.csdn.net/heyangyi_19940703/article/details/51241432