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 = "\t";
        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 = "\t";
        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方法。

  

posted @   shine声  阅读(316)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示