# 原型模式

属于创建型模式。
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
原型模式是通过拷贝一个现有对象生成新的对象,当直接创建对象的代价比较大时,则采用这种模式。

拷贝分为深拷贝和浅拷贝,接下来将分别介绍。

使用场景:

  1. 资源优化
  2. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等
  3. 性能和安全要求的场景
  4. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
  5. 一个对象多个修改者的场景
  6. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用
  7. 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现。通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者

# 深拷贝和浅拷贝

当复制一个对象时,由于其属性复制后产生的效果不同,而产生了深拷贝与浅拷贝。
对于值类型,深拷贝和浅拷贝都是一样的,都是对原始数据的复制,修改原始数据,不会对复制数据产生影响。
对于静态的部分,都不会复制。
两者的区别,在于对引用属性的复制。

# 浅拷贝

创建一个新对象,如果字段是引用类型,则复制引用但不复制引用的对象,因此,原始对象和其副本都引用同一个对象

# 深拷贝

创建一个新对象,如果字段是引用类型,则复制引用和引用的对象,因此,原始对象和其副本是不同的两个对象

# 浅拷贝实现

# 类图

img

# 代码

# 需要拷贝的类

namespace CreationalPatterns_PrototypePattern.ShallowCopy
{
    /// <summary>
    /// 效果
    /// </summary>
    public class Effect
    {
        public string EffectName;
        public Effect(string effectName)
        {
            EffectName = effectName;
        }
    }
}
namespace CreationalPatterns_PrototypePattern.ShallowCopy
{
    /// <summary>
    /// 形状
    /// </summary>
    public class Shape
    {
        public string ShapName;
        public Effect MainEffect;
        public Shape(string shapName, string effectName)
        {
            ShapName = shapName;
            MainEffect = new Effect(effectName);
        }
        /// <summary>
        /// 形状和效果
        /// </summary>
        public void MyShap()
        {
            Console.WriteLine("ShapName: " + ShapName + "\nEffectName: " + MainEffect.EffectName);
        }
        /// <summary>
        /// 生成克隆(浅拷贝)
        /// </summary>
        public Shape GetClone()
        {
            return (Shape)MemberwiseClone();
        }
    }
}

# 测试

namespace CreationalPatterns_PrototypePattern.ShallowCopy
{
    public class Program
    {
        private static void Main()
        {
            Shape shape_0 = new Shape("shape_0", "Transparent");
            Shape shape_1 = shape_0.GetClone();
            // 注意,这里将引用指向了新的 string 类型的对象
            shape_1.ShapName = "shape_1";
            shape_1.MainEffect.EffectName = "Opaque";
            shape_0.MyShap();
            Console.WriteLine();
            shape_1.MyShap();
        }
    }
}

运行结果:
ShapName: shape_0
EffectName: Opaque

ShapName: shape_1
EffectName: Opaque

# 深拷贝实现

  • 使用对象复制方法:如果类中包含引用类型的成员变量,可以通过递归调用成员变量的复制方法来实现深拷贝。
  • 使用序列化和反序列化:这是一种常见的实现深拷贝的方式。可以通过将对象进行序列化为字节流,然后再反序列化生成一个全新的对象。

# 使用对象复制方法

  • 相较于浅拷贝,只需要更改 Shape 类
  • 使用不同的命名空间做出区分
using CreationalPatterns_PrototypePattern.ShallowCopy;
namespace CreationalPatterns_PrototypePattern.DeepCopy_ObjectCopy
{
    /// <summary>
    /// 形状
    /// </summary>
    public class Shape
    {
        public string ShapName;
        public Effect MainEffect;
        public Shape(string shapName, string effectName)
        {
            ShapName = shapName;
            MainEffect = new Effect(effectName);
        }
        /// <summary>
        /// 形状和效果
        /// </summary>
        public void MyShap()
        {
            Console.WriteLine("ShapName: " + ShapName + "\nEffectName: " + MainEffect.EffectName);
        }
        /// <summary>
        /// 生成克隆(深拷贝)
        /// </summary>
        public Shape GetClone()
        {
            Shape temp = (Shape)MemberwiseClone();
            temp.MainEffect = new Effect(this.MainEffect.EffectName);
            return temp;
        }
    }
}

用于测试的代码与浅拷贝相同,但运行结果不同:
ShapName: shape_0
EffectName: Transparent

ShapName: shape_1
EffectName: Opaque

# 使用序列化和反序列化

# 类图

img

# 代码

# 处理序列化和反序列化

  • 要进行深拷贝的类及其成员必须是可序列化的,所以需要将它们标记为 [Serializable]
using System.Runtime.Serialization.Formatters.Binary;
namespace CreationalPatterns_PrototypePattern.DeepCopy_Serialization
{
    public class DeepCopyHelper
    {
        public static T DeepCopy<T>(T obj)
        {
            if (obj == null)
            {
                return default(T);
            }
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            using (stream)
            {
                formatter.Serialize(stream, obj);
                stream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(stream);
            }
        }
    }
}

# 用于拷贝的类

namespace CreationalPatterns_PrototypePattern.DeepCopy_Serialization
{
    [Serializable]
    /// <summary>
    /// 效果
    /// </summary>
    public class Effect
    {
        public string EffectName;
        public Effect(string effectName)
        {
            EffectName = effectName;
        }
    }
}
namespace CreationalPatterns_PrototypePattern.DeepCopy_Serialization
{
    [Serializable]
    /// <summary>
    /// 形状
    /// </summary>
    public class Shape
    {
        public string ShapName;
        public Effect MainEffect;
        public Shape(string shapName, string effectName)
        {
            ShapName = shapName;
            MainEffect = new Effect(effectName);
        }
        /// <summary>
        /// 形状和效果
        /// </summary>
        public void MyShap()
        {
            Console.WriteLine("ShapName: " + ShapName + "\nEffectName: " + MainEffect.EffectName);
        }
        /// <summary>
        /// 生成克隆(深拷贝)
        /// </summary>
        public Shape GetClone()
        {
            return DeepCopyHelper.DeepCopy<Shape>(this);
        }
    }
}

# 测试

namespace CreationalPatterns_PrototypePattern.DeepCopy_Serialization
{
    public class Program
    {
        private static void Main()
        {
            Shape shape_0 = new Shape("shape_0", "Transparent");
            Shape shape_1 = shape_0.GetClone();
            // 注意,这里将引用指向了新的 string 类型的对象
            shape_1.ShapName = "shape_1";
            shape_1.MainEffect.EffectName = "Opaque";
            shape_0.MyShap();
            Console.WriteLine();
            shape_1.MyShap();
        }
    }
}

运行结果:
ShapName: shape_0
EffectName: Transparent

ShapName: shape_1
EffectName: Opaque

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Maikire 微信支付

微信支付

Maikire 支付宝

支付宝

Maikire 贝宝

贝宝