首页 > Windows开发 > 详细

C#设计模式(6)——原型模式

时间:2019-07-25 09:52:02      阅读:94      评论:0      收藏:0      [点我收藏+]

出处:https://www.cnblogs.com/wyy1234/

 

阅读目录

 


1.原型模式介绍

  在软件系统开发中,有时候会遇到这样的情况:我们需要用到多个相同实例,最简单直接的方法是通过多次调用new方法来创建相同的实例。如下:

Person person=new Person(){Name="jack",Age=20};
Person person2=new Person(){Name="jack",Age=20};
Person person3=new Person(){Name="jack",Age=20};

  但是有一个问题,如果我用要使用的实例创建起来十分耗费资源,或者创建起来步骤比较繁琐,上边的代码缺点就暴露出来了:耗费资源,每次创建实例都要重复繁琐的创建过程。原始模式可以很好地解决这个问题,使用原型模式我们不需要每次都new一个新的实例,而是通过拷贝原有的对象来完成创建,这样我们就不需要在内存中创建多个对象,也不需要重复复杂的创建过程了。下边以克隆人为例解释原型模式的用法,代码非常简单。

人类原型类,提供了一个克隆抽象方法:

技术分享图片
   /// <summary>
    /// 人类原型抽象类
    /// </summary>
    public abstract class PersonPrototype 
    {
        public abstract object clone();
    }
技术分享图片

人类继承原型类,表示人类可以被克隆,每个人都有名字,年龄和住址:

技术分享图片
   /// <summary>
    /// Person
    /// </summary>
    public class Person: PersonPrototype
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Address Address { get; set; }

        public override object clone()
        {
            //MemberwiseClone方法实现浅拷贝
            return this.MemberwiseClone();
        }
    }

    /// <summary>
    /// 住址
    /// </summary>
    public class Address
    {
        public string Province { get; set; }
        public string City { get; set; }
    }
技术分享图片

客户端代码:

技术分享图片
        static void Main(string[] args)
        {
            //创建一个person实例
            Person person1 = new Person()
            {
                Name = "jack",
                Age = 20,
                Address = new Address{Province = "山东",City = "青岛"}
            };
            //一个克隆人,通过clone方法替代了new方法
            Person clonePerson = (Person)person1.clone();

            Console.WriteLine($"person1的name:{person1.Name},年龄:{person1.Age}," +
                              $"省份:{person1.Address.Province},城市:{person1.Address.City}");
            Console.WriteLine($"克隆人的name:{clonePerson.Name},年龄:{clonePerson.Age}," +
                              $"省份:{clonePerson.Address.Province},城市:{clonePerson.Address.City}");
            Console.ReadKey();
        }
技术分享图片

运行结果如下:

技术分享图片

我们可以看到,通过clone方法成功获取了一个相同的person实例。

这里需要注意一点:通过object.MemberWiseClone()获取一个对象的实例属于浅拷贝,对实例的简单类型属性进行全值拷贝(包含string类型),对复杂类型属性只拷贝了引用。客户端代码如下

 

技术分享图片
       static void Main(string[] args)
        {
            //创建一个person实例
            Person person1 = new Person()
            {
                Name = "jack",
                Age = 20,
                Address = new Address{Province = "山东", City = "青岛"}
            };
            //一个克隆人
            Person clonePerson = (Person)person1.clone();
            clonePerson.Name = "tom";
            clonePerson.Age = 22;
            clonePerson.Address.Province = "浙江";
            clonePerson.Address.City = "杭州";


            Console.WriteLine($"person1的name:{person1.Name},年龄:{person1.Age}," +
                              $"省份:{person1.Address.Province},城市:{person1.Address.City}");
            Console.WriteLine($"克隆人的name:{clonePerson.Name},年龄:{clonePerson.Age}," +
                              $"省份:{clonePerson.Address.Province},城市:{clonePerson.Address.City}");
            Console.ReadKey();
        }
    }
技术分享图片

运行结果:对于复杂类型Address,修改clonePerson的省份和城市,person1的Address也修改了。而修改clonePerson的名字,person1的名字没有变。

技术分享图片

修改clonePerson的名字,person1的名字没有变,这一点是MemberwishClone方法和直接赋值的区别,我们修改客户端代码,将

技术分享图片
       static void Main(string[] args)
        {
            //创建一个person实例
            Person person1 = new Person()
            {
                Name = "jack",
                Age = 20,
                Address = new Address{Province = "山东",City = "青岛"}
            };
            //这里使用直接赋值,而不是clone
            Person clonePerson = person1;
            clonePerson.Name = "tom";
            clonePerson.Age = 22;
            clonePerson.Address.Province = "浙江";
            clonePerson.Address.City = "杭州";


            Console.WriteLine($"person1的name:{person1.Name},年龄:{person1.Age}," +
                              $"省份:{person1.Address.Province},城市:{person1.Address.City}");
            Console.WriteLine($"克隆人的name:{clonePerson.Name},年龄:{clonePerson.Age}," +
                              $"省份:{clonePerson.Address.Province},城市:{clonePerson.Address.City}");
            Console.ReadKey();
        }
技术分享图片

运行结果:直接赋值修改字符串类型的属性(name)原始实例也会修改

技术分享图片

 2.小结

上边例子的类图

技术分享图片

原型模式的优点:

  1.隐藏了创建实例的繁琐过程,只需通过Clone方法就可以获取实例对象

  2.使用浅拷贝替代new,减少资源消耗

原型模式的缺点:

  1.需要添加一个Clone方法,C#中一般使用MemberwishClone方法来获取实例的浅拷贝副本。

补充:如果想实现深拷贝常用的有两种方法:①将原始实例序列化,然后反序列化赋值给副本对象;②浅拷贝+递归的方式,类似于遍历文件夹,对所有的复杂属性、复杂属性内部的复杂属性都进行浅拷贝。

C#设计模式(6)——原型模式

原文:https://www.cnblogs.com/frank0812/p/11241943.html

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