ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

创建型设计模式 - 原型

2021-05-30 11:05:13  阅读:168  来源: 互联网

标签:obj 创建 原型 product2 Console 拷贝 设计模式 type public


原型模式

概念

原型模式是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;
        }

标签:obj,创建,原型,product2,Console,拷贝,设计模式,type,public
来源: https://www.cnblogs.com/Huangxiaomao/p/14827277.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有