首页 > 其他 > 详细

创建型设计模式 - 原型

时间:2021-05-30 15:34:23      阅读:8      评论:0      收藏:0      [点我收藏+]

原型模式

概念

原型模式是23种设计模式之一。用于创建重复的对象。

浅拷贝与深拷贝

浅拷贝: 自带的MemberwiseClone方法,这种方法实现的浅拷贝,如果对象中包含有引用类型,拷贝的是栈中的地址,指向的都是同一个堆地址。
深拷贝: 值类型和引用类型完全拷贝。有两种方法可以实现,第一个是利用序列化和反序列化;第二是利用反射加上递归。

核心代码

23种设计模式github代码

  
 using System;
using System.Collections.Generic;
using System.Text;

namespace CreateTypeDesignPatterns
{

    public class Prototype
    {

        public static void Show()
        {
              PrototypeProduct product = new PrototypeProduct
            {
                Name = "product1",
                Num = 1,
                type = new Type() { TypeId = 1 }
            };
            var product2 = product.ShallowClone();
            product2.Num = 2;
            product2.Name = "product2";
            product2.type.TypeId = 2;
          
            //值类型完全拷贝
            Console.WriteLine(product.Num);//1
            Console.WriteLine(product2.Num);//2

            //不是说引用类型只拷贝地址吗?为什么修改了produtct2的Name值,Product1的值还是原来的呢?
            //引用类型拷贝地址是对的,但是字符串类型有的特殊,因为字符串类型是不可变的。修改product2的Name值相当于新创建了一个string类型的值
            Console.WriteLine(product.Name);//product1
            Console.WriteLine(product2.Name);//product2

            //引用类型的浅拷贝,这里就体现出来了
            //修改了product2的type,product1中的type也随着改变
            Console.WriteLine(product.type.TypeId); //2
            Console.WriteLine(product2.type.TypeId); //2  

            
            product2.type = new Type() { TypeId = 3 };
            //这里修改了product2中的type值,为什么product中的type没有发生改变呢?
            //因为product2重新创建了一个type,和product中的type指向的不是同一个堆内存空间了
            //上面所提到的字符串可以参考这一条
            Console.WriteLine(product.type.TypeId); //2
            Console.WriteLine(product2.type.TypeId); //3

        }
    }

    public class PrototypeProduct
    {
        
        public int Num { get; set; }
        public string Name { get; set; }

        public Type type { get; set; }

        //浅拷贝
        public PrototypeProduct ShallowClone()
        {
            return (PrototypeProduct)this.MemberwiseClone();
        }
    }

    public class Type 
    {
        public int TypeId { get; set; }
    }
}

深拷贝实现的两种方式

序列化 + 内存流
要保证相关对象有[Serializable]特性

     /// <summary>
        /// 通过序列化+二进制  实现深拷贝
        /// 原对象相关的类必须添加Serializable
        /// </summary>
        public static object DeepCloneBySerialize(this object obj)
        {
            if (obj == null || obj is string || obj.GetType().IsValueType)
            {
                return obj;
            }
            using (MemoryStream ms = new MemoryStream())
            {
                //二进制序列化器
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                //将对象写入内存流
                binaryFormatter.Serialize(ms, obj);
                //将当前流中的位置设置为指定值
                ms.Seek(0, SeekOrigin.Begin);
                //反序列化成对象
                object result = binaryFormatter.Deserialize(ms);
                return result;
            }
        }

反射 + 递归

/// <summary>
        /// 通过反射 + 递归   实现深拷贝
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static object DeepCloneByReflect(this object obj)
        {
            //如果是值类型或者是字符串类型返回原值
            //递归出口
            if (obj == null || obj is string || obj.GetType().IsValueType)
            {
                return obj;
            }

            var type = obj.GetType();
            //根据对象的type类型,创建一个新的空对象
            //构造函数模式是公开的
            object result = Activator.CreateInstance(type);
            //根据type值可以获取类中所有的属性和字段
            FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
            foreach (FieldInfo field in fieldInfos)
            {
                //这里用到了递归
                //将原对象的属性值一一赋值到新对象中,因为原对象的属性值有可能是多层引用值,所以要用到递归
                //递归的出口就是这个属性的值是值类型或者是字符串类型
                field.SetValue(result,field.GetValue(obj).DeepCloneByReflect());
            }
            return result;
        }

创建型设计模式 - 原型

原文:https://www.cnblogs.com/Huangxiaomao/p/14827277.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!