zoukankan      html  css  js  c++  java
  • C# 设计模式-原型模式

    一.介绍  

      原型模式(Prototype Pattern)。属于创建型模式。用原型实例指向创建对象的种类,并且通过拷贝这些原型创建新的对象。

    二.实现

      简单来说,原型模式可以直接复制一个现有的对象,而不需要重新new操作去创建。这种创建分两种方式,浅拷贝和深拷贝。

      1.浅拷贝

      定义一个接口IPerson来规范People。ICloneable是系统自带的接口,来定义需要用clone方法的。

    public interface IPerson
    {
        object Clone();
    }
    
    public class Person : IPerson, ICloneable
    {
        public string Name { get; set; }
        public Address Address { get; set; }
    
        public override string ToString()
        {
            var newLine = Environment.NewLine;
            var indent = "	";
            var str = $"Name:{Name}{newLine}Address:{newLine}{indent}Province:{Address.Province}{newLine}{indent}City:{Address.City}{newLine}";
            return str;
        }
    
        /// <summary>
        /// 浅拷贝
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }
    
    public class Address
    {
        public string City { get; set; }
        public string Province { get; set; }
    }

      代码实现。

    public static void Main(string[] args)
    {
        var person1 = new Person { Name = "aaa", Address = new Address { City = "Wuhan", Province = "HuBei" } };
        Console.WriteLine("Person1 is ");
        Console.WriteLine(person1.ToString());
    
        var person2 = person1.Clone() as Person;
        Console.WriteLine("Cloned Person2 is ");
        Console.WriteLine(person2.ToString());
    
    
        Console.WriteLine("============= 修改原对象 =============");
        person1.Name = "bbb";
        person1.Address.Province = "Shanghai";
        person1.Address.City = "shanghai";
    
        Console.WriteLine("Person1 is");
        Console.WriteLine(person1.ToString());
    
        Console.WriteLine("Cloned Person2 is ");
        Console.WriteLine(person2.ToString());
    
    
        Console.WriteLine("============= 修改复制对象 =============");
        person2.Name = "ccc";
        person2.Address.Province = "Guangdong";
        person2.Address.City = "GuangZhou";
    
        Console.WriteLine("Person1 is");
        Console.WriteLine(person1.ToString());
    
        Console.WriteLine("Cloned Person2 is ");
        Console.WriteLine(person2.ToString());
    }

      结果如图。

       从结果可见,people修改了属性值,对people2的属性值没有影响。反过来,people2修改属性值对people也没有影响。但两者address的引用修改后,都互相影响。

      2.深拷贝

    public interface IPerson
    {
        object Clone();
    }
    
    [Serializable]
    public class Person : IPerson, ICloneable
    {
        public string Name { get; set; }
        public Address Address { get; set; }
    
        public override string ToString()
        {
            var newLine = Environment.NewLine;
            var indent = "	";
            var str = $"Name:{Name}{newLine}Address:{newLine}{indent}Province:{Address.Province}{newLine}{indent}City:{Address.City}{newLine}";
            return str;
        }
    
        /// <summary>
        /// 深拷贝
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Person));
            using (var stream = new System.IO.MemoryStream())
            {
                serializer.Serialize(stream, this);
                stream.Seek(0, System.IO.SeekOrigin.Begin);
                return serializer.Deserialize(stream) as Person;
            }
        }
    }
    
    [Serializable]
    public class Address
    {
        public string City { get; set; }
        public string Province { get; set; }
    }

      执行方法和上面一样,结果是属性值和引用值都不相互影响。通过序列化和反序列化创建了一个新的对象,这样拷贝出来的类指向就不会和原有的类一样。

    三.总结

      优点:

      1.隐藏了创建实例的繁琐过程,只需要通过clone方法就能获取实例。

      2.使用拷贝代替new,减少资源损耗。

      缺点:

      需要在每个需要拷贝的类中实现clone方法。

      

  • 相关阅读:
    fedora如何删除某个包且不删除依赖它的相关包
    git分支切换时的时间戳问题
    [Centos] ERROR: Could not find useradd in chroot, maybe the install failed?
    linux通过python设置系统默认编码
    linux设置系统时间和时区
    python: "TypeError: 'type' object is not subscriptable"
    如何搭建http服务仓库
    [转载]RPM中SPEC常用路径以及宏变量
    spec文件写作规范
    GeoServer中利用SLD配图之矢量图层配图
  • 原文地址:https://www.cnblogs.com/shadoll/p/14267015.html
Copyright © 2011-2022 走看看