设计模式之笔记--原型模式(Prototype)

Posted sunny906

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之笔记--原型模式(Prototype)相关的知识,希望对你有一定的参考价值。

原型模式(Prototype)

类图

技术分享

描述

原型模式:

提供一个克隆自身的接口--Clone方法。

应用场景

定义一个学生类,包含一个值类型(int)的Age属性、两个引用类型Name(string)和Course属性。

    public class Course
    {
        public string Name { get; set; }
    }

    public class Student : ICloneable
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Course Course { get; set; }

        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }

        static void Main(string[] args)
        {
            string value = ConfigurationManager.AppSettings["prototypePattern"];
            Student student = (Student)Assembly.Load(value.Substring(0, value.IndexOf(.))).CreateInstance(value);
            student.Name = "Jim";
            student.Age = 20;
            student.Course = new Course() { Name = "C++" };
            Console.WriteLine("student:" + student.Name + "\t" + student.Age + "\t" + student.Course.Name);

            Console.WriteLine();
            Student student1 = (Student)student.Clone();
            student1.Name = "Tom";
            student1.Age = 21;
            student1.Course.Name = "C#";
            Console.WriteLine("student:" + student.Name + "\t" + student.Age + "\t" + student.Course.Name);
            Console.WriteLine("student1:" + student1.Name + "\t" + student1.Age + "\t" + student1.Course.Name);

            Console.WriteLine();
            student1.Course.Name = "Java";
            Console.WriteLine("student:" + student.Name + "\t" + student.Age + "\t" + student.Course.Name);
            Console.WriteLine("student1:" + student1.Name + "\t" + student1.Age + "\t" + student1.Course.Name);
        }

输出:

student:Jim 20 C++

student:Jim 20 C#
student1:Tom 21 C#

student:Jim 20 Java
student1:Tom 21 Java

      从打印的结果可以看出,给原对象student拷贝一个新的student1对象并给student1属性赋值之后,原对象student的Age和Name没变,CourseName却变了。原因是拷贝之后,student把student1的Age和Name复制了一份,而student1的Course依然指向student的Course地址,所以,当student1的CourseName改变时,student的CourseName也随之改变,这就是浅拷贝。

      但是在实际应用中,往往不希望发生这样的事情,也就是不能因为拷贝对象发生变化而影响到原对象。原因很简单,不能因为Tom选了C#这门课就要求Jim也必须把已经选的C++这门课改成C#。要解决这个问题,就需要拷贝一个全新的对象,即深拷贝。

下面把Student类和Course类小改一下,通过序列化和反序列化来创建一个全新的student:

    [Serializable]
    public class Course
    {
        public string Name { get; set; }
    }

    [Serializable]
    public class Student : ICloneable
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Course Course { get; set; }

        public object Clone()
        {
            using (Stream objectStream = new MemoryStream())
            {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(objectStream, this);
                objectStream.Seek(0, SeekOrigin.Begin);
                return formatter.Deserialize(objectStream);
            }
        }
    }

输出:

student:Jim 20 C++

student:Jim 20 C++
student1:Tom 21 C#

student:Jim 20 C++
student1:Tom 21 Java

浅拷贝和深拷贝的区别:

浅拷贝:对值类型和string类型直接拷贝,对引用类型共用同一个指针;两个对象之间存在耦合;

深拷贝:给对象拷贝一个全新的对象,两个对象之间的耦合度为0。

以上是关于设计模式之笔记--原型模式(Prototype)的主要内容,如果未能解决你的问题,请参考以下文章

JAVA设计模式之原型模式

JAVA设计模式之原型模式(prototype)

设计模式之原型模式

Java学习笔记——设计模式之六.原型模式(浅克隆和深克隆)

设计模式---对象创建模式之原型模式(prototype)

设计模式之原型模式