原型模式(Prototype Pattern)

1、概述

在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构。这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适。那么如何封装这种动态的变化?从而使依赖于这些易变对象的客户程序不随着产品类变化?

2、意图

原型模式是通过现有的一个对象,复制出更多的此类型的对象以供使用。

3、结构图

截图01

图解说明

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、运行结果

result1

可以看出,浅拷贝中,拷贝对象中的引用对象(RGBColor类对象)与原对象中的对应的引用对象(RGBColor类对象)指向同一个内存地址,而值信息则拷贝对象有一个另外的拷贝。

深拷贝中值变量和引用变量都重新开辟了一个内存,所以拷贝对象与原对象中的变量间所在的内存不一样。

原文地址:https://www.cnblogs.com/smallstone/p/1673721.html