原型模式(Prototype Pattern)
1、概述
在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构。这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适。那么如何封装这种动态的变化?从而使依赖于这些易变对象的客户程序不随着产品类变化?
2、意图
原型模式是通过现有的一个对象,复制出更多的此类型的对象以供使用。
3、结构图
图解说明
UsePrototype类是用户类也是程序启动类
RGBColor类是一个颜色类
ColorPrototype类是抽象类,含有Clone方法
ConcretePrototype 类继承ColorPrototype,实现浅拷贝。
ConcretePrototypeDeep类继承ColorPrototype,实现深拷贝
关于深拷贝和浅拷贝简单的说:
浅拷贝(Shallow Copy影子克隆):只复制对象的基本类型。对象类型,仍属于原来的引用。
深拷贝(Deep Copy 深度克隆):不仅复制对象的基本类,同时也复制原对象中的对象.完全产生新对象。
4、代码的实现
注意:代码中的深拷贝是使用序列化实现的。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Serialization.Formatters.Binary; using System.IO; namespace PrototypePattern { [Serializable] public abstract class ColorPrototype { public abstract ColorPrototype Clone(); } [Serializable] public class RGBColor { /// <summary> /// 颜色的三色素:红、绿、兰 /// </summary> private int _red,_green,_blue; public RGBColor(int red, int green, int blue) { this._red = red; this._green = green; this._blue = blue; } public int RED { get { return this._red; } set { this._red = value; } } public int GREEN { get { return this._green; } set { this._green = value; } } public int BLUE { get { return this._blue; } set { this._blue = value; } } } /// <summary> /// 实现浅拷贝 /// </summary> public class ConcretePrototype :ColorPrototype { /// <summary> /// 长、宽、高 /// </summary> private int _lenth, _hign, _wide; private RGBColor _color = null; /// <summary> /// 构造函数 /// </summary> /// <param name="length"></param> /// <param name="hign"></param> /// <param name="wide"></param> public ConcretePrototype(int length, int hign, int wide,RGBColor color) { this._wide = wide; this._lenth = length; this._hign = hign; this._color = color; } public void SetRectangle(int length, int hign, int wide) { this._lenth = length; this._wide = wide; this._hign = hign; } public RGBColor SGRGBColor { set { this._color = value; } get { return this._color; } } /// <summary> /// 浅拷贝,只复制对象的基本类型.对象类型,仍属于原来的引用. /// </summary> /// <returns></returns> public override ColorPrototype Clone() { //创建当前ConcretePrototype的浅拷贝 return (ColorPrototype)this.MemberwiseClone(); } /// <summary> /// 将对象的信息显示出来 /// </summary> public void Display() { //注意this._lenth, this._hign, this._wide是值类型 Console.WriteLine("This rectangle's area: ({0},{1},{2})", this._lenth, this._hign, this._wide); //注意this._color是引用类型 Console.WriteLine("This rectangle's color: ({0},{1},{2})", this._color.RED,this._color.GREEN,this._color.BLUE); } } /// <summary> /// 深拷贝 /// </summary> [Serializable] public class ConcretePrototypeDeep : ColorPrototype { /// <summary> /// 长、宽、高 /// </summary> private int _lenth, _hign, _wide; private RGBColor _color = null; /// <summary> /// 构造函数 /// </summary> /// <param name="length"></param> /// <param name="hign"></param> /// <param name="wide"></param> public ConcretePrototypeDeep(int length, int hign, int wide, RGBColor color) { this._wide = wide; this._lenth = length; this._hign = hign; this._color = color; } public void SetRectangle(int length, int hign, int wide) { this._lenth = length; this._wide = wide; this._hign = hign; } public RGBColor SGRGBColor { set { this._color = value; } get { return this._color; } } /// <summary> /// 深度拷贝,不仅复制对象的基本类,同时也复制原对象中的对象.完全产生新对象。 /// </summary> /// <returns></returns> public override ColorPrototype Clone() { MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, this); stream.Position = 0; return (ColorPrototype)formatter.Deserialize(stream); } public void Display() { Console.WriteLine("This rectangle's area: ({0},{1},{2})", this._lenth, this._hign, this._wide); Console.WriteLine("This rectangle's color: ({0},{1},{2})", this._color.RED,this._color.GREEN,this._color.BLUE); } } public class UsePrototype { public static void Main(string[] args) { Console.WriteLine("====== ====== 浅拷贝 ====== ======"); ColorPrototype colorPrototype = new ConcretePrototype(100, 200, 300,new RGBColor(20,100,130)); Console.WriteLine("原对象信息为:"); ((ConcretePrototype)colorPrototype).Display(); ColorPrototype colorPrototypeClone = colorPrototype.Clone(); ((ConcretePrototype)colorPrototypeClone).SetRectangle(150, 250, 350); ((ConcretePrototype)colorPrototypeClone).SGRGBColor.RED = 30; ((ConcretePrototype)colorPrototypeClone).SGRGBColor.GREEN = 120; ((ConcretePrototype)colorPrototypeClone).SGRGBColor.BLUE = 100; Console.WriteLine("拷贝对象信息改变后为:"); ((ConcretePrototype)colorPrototypeClone).Display(); Console.WriteLine("只复制对象的基本类型.对象类型,仍属于原来的引用"); ((ConcretePrototype)colorPrototype).Display(); Console.WriteLine("====== ====== 深拷贝 ====== ======"); colorPrototype = new ConcretePrototypeDeep(100, 200, 300, new RGBColor(20, 100, 130)); Console.WriteLine("原对象信息为:"); ((ConcretePrototypeDeep)colorPrototype).Display(); colorPrototypeClone = colorPrototype.Clone(); ((ConcretePrototypeDeep)colorPrototypeClone).SetRectangle(150, 250, 350); ((ConcretePrototypeDeep)colorPrototypeClone).SGRGBColor.RED = 30; ((ConcretePrototypeDeep)colorPrototypeClone).SGRGBColor.GREEN = 120; ((ConcretePrototypeDeep)colorPrototypeClone).SGRGBColor.BLUE = 100; Console.WriteLine("拷贝对象信息改变后为:"); ((ConcretePrototypeDeep)colorPrototypeClone).Display(); Console.WriteLine("不仅复制对象的基本类,同时也复制原对象中的对象.完全产生新对象。"); ((ConcretePrototypeDeep)colorPrototype).Display(); } } }
5、运行结果
可以看出,浅拷贝中,拷贝对象中的引用对象(RGBColor类对象)与原对象中的对应的引用对象(RGBColor类对象)指向同一个内存地址,而值信息则拷贝对象有一个另外的拷贝。
深拷贝中值变量和引用变量都重新开辟了一个内存,所以拷贝对象与原对象中的变量间所在的内存不一样。