原型模式

作者: HapplyFox | 来源:发表于2018-08-08 16:06 被阅读4次

    原型模式的结构
    原型模式包含以下3个角色:
    •Prototype(抽象原型类)
    •ConcretePrototype(具体原型类)
    •Client(客户类)

    浅克隆与深克隆
    浅克隆(Shallow Clone):当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制
    深克隆(Deep Clone):除了对象本身被复制外,对象所包含的所有成员变量也将被复制

    原型核心代码

        /// <summary>
        /// 班级
        /// </summary>
        [Serializable]
        public class Class
        {
            public int Num { get; set; }
            public string Remark { get; set; }
        }
    
        [Serializable]
        public class StudentPrototype
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public Class Class { get; set; }
    
            private StudentPrototype() { }
    
            private static readonly StudentPrototype _studentPrototype = null;
    
            static StudentPrototype()
            {
                _studentPrototype = new StudentPrototype()
                {
                    Id = 0,
                    Name = "复制",
                    Class = new Class()
                    {
                        Num = 100,
                        Remark = "100"
                    }
                };
            }
            public static StudentPrototype CreateInstanceClone()
            {
                StudentPrototype studentPrototype = (StudentPrototype)_studentPrototype.MemberwiseClone();
                //这样就是深clone,如果没有这段,Class实例就是浅克隆
                studentPrototype.Class = new Class()
                {
                    Num = 1,
                    Remark = "软谋高级班"
                };
    
                return studentPrototype;
            }
    
            public static StudentPrototype CreateInstanceSerialize()
            {
                //序列化方式创建克隆,需要保证被克隆的对象具有 serialize 特性标签
                return SerializeHelper.DeepClone<StudentPrototype>(_studentPrototype);
            }
        }  
    

    原型模式的理解
    原型模式在我的理解中时基于单例模式的一个扩展,在保证实例对象唯一的情况下,能快递new出不同的新实例
    对外提供一个接口 CreateCloneInstance创建克隆对象

    浅层次克隆

                    Console.WriteLine("*****浅层次克隆Start**********");
                    var box1 = StudentPrototype.CreateInstanceClone();
                    Console.WriteLine($"Id={box1.Id} name={box1.Name}");
                    var box2 = StudentPrototype.CreateInstanceClone();
                    box2.Id = 10;
                    box2.Name = "测试";
                    Console.WriteLine($"Id={box2.Id} name={box2.Name}");
                    Console.WriteLine("*****浅层次克隆End**********");
    

    深层次克隆1 失败+成功方法

                {
                    //对值类型的克隆修改值,不会影响克隆出的新对象的内容。但是引用类型的克隆有需要注意的点,Class是引用类型的值,具有Num和Remark俩个属性。如果使用下面的写法 box1.Class.Num=***,实际上源对象Class地址和克隆对象地址相同,修改一个相当于全部修改了,并没有实现我们想要的克隆效果
                    Console.WriteLine("*****深层次克隆 Start**********");
                    var box1 = StudentPrototype.CreateInstanceClone();
                    box1.Class.Num = 10;
                    box1.Class.Remark = "备注";
                    Console.WriteLine($"Id={box1.Id} name={box1.Name} ClassNum={box1.Class.Num } Remark={box1.Class.Remark }");
                    var box2 = StudentPrototype.CreateInstanceClone();
                    box2.Id = 10;
                    box2.Name = "测试";
                    Console.WriteLine($"Id={box2.Id} name={box2.Name} ClassNum={box2.Class.Num } Remark={box2.Class.Remark }");
                    Console.WriteLine("*****深层次克隆 End**********");
                }
    

    深层次克隆2 序列化

       {
                    //使用序列化的方式进行克隆原理,因为深层次克隆的主要问题是引用类型克隆时还是相同地址
                    //我们先将初始对象序列化,在将得到的值进行反序列化,这样便能保证生成的对象存在不同的地址引用
                    Console.WriteLine("*****深层次克隆2 序列化Start**********");
                    var box1 = StudentPrototype.CreateInstanceSerialize();
                    box1.Class.Num = 10;
                    box1.Class.Remark = "备注";
                    Console.WriteLine($"Id={box1.Id} name={box1.Name} ClassNum={box1.Class.Num } Remark={box1.Class.Remark }");
                    var box2 = StudentPrototype.CreateInstanceSerialize();
                    box2.Id = 10;
                    box2.Name = "测试";
                    Console.WriteLine($"Id={box2.Id} name={box2.Name} ClassNum={box2.Class.Num } Remark={box2.Class.Remark }");
                    Console.WriteLine("*****深层次克隆2  序列化End**********");
                }
    

    相关文章

      网友评论

        本文标题:原型模式

        本文链接:https://www.haomeiwen.com/subject/yqcxbftx.html