设计模式之 原型模式 C# 范例

原型模式(Prototype Pattern)是一种通过克隆(复制)现有对象来创建新对象的创建型设计模式。它可以避免重复创建相似对象的繁琐过程,尤其适合在复杂对象的创建过程中节省时间和资源。

1. 原型模式的简单示例

我们通过一个简单的示例来展示原型模式的使用。假设我们有一个 Person 类,表示一个人,它包含姓名、年龄以及地址等属性。通过原型模式,我们可以克隆现有的 Person 对象来创建新的 Person 对象,而不是通过构造函数重新创建。

步骤:

  1. 定义原型接口 :让所有需要克隆的类实现该接口,提供 Clone() 方法。
  2. 实现具体原型类:每个具体类实现接口并提供克隆的实现。
  3. 客户端:使用克隆方法创建新对象,而不是通过构造函数。
1.1 定义 IPrototype 接口

public interface IPrototype { IPrototype Clone(); }

1.2 实现具体的 Person
cs 复制代码
public class Person : IPrototype
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }

    // 构造函数
    public Person(string name, int age, string address)
    {
        Name = name;
        Age = age;
        Address = address;
    }

    // 克隆方法
    public IPrototype Clone()
    {
        // 浅拷贝:复制当前对象的属性,适用于没有引用类型属性的场景
        return (IPrototype)this.MemberwiseClone();
    }

    public void DisplayInfo()
    {
        Console.WriteLine($"Name: {Name}, Age: {Age}, Address: {Address}");
    }
}
1.3 客户端代码
cs 复制代码
class Program
{
    static void Main(string[] args)
    {
        // 创建原型对象
        Person person1 = new Person("Alice", 30, "123 Main St");
        person1.DisplayInfo();

        // 使用克隆方法复制一个新的对象
        Person person2 = (Person)person1.Clone();
        person2.Name = "Bob";  // 修改克隆对象的属性
        person2.Age = 25;
        person2.Address = "456 Elm St";
        person2.DisplayInfo();

        // 确认原型对象未改变
        person1.DisplayInfo();
    }
}

输出:

cs 复制代码
Name: Alice, Age: 30, Address: 123 Main St
Name: Bob, Age: 25, Address: 456 Elm St
Name: Alice, Age: 30, Address: 123 Main St

在这个示例中,person1 是原型对象,我们使用 Clone() 方法克隆了一个新的 person2 对象,并对其属性进行了修改。原型对象 person1 保持不变,证明原型模式通过克隆创建的新对象与原对象是不同的。

2. 深拷贝示例

如果 Person 类中包含引用类型的属性(比如 Address 是一个对象),浅拷贝(通过 MemberwiseClone())可能会导致引用类型字段被共享。为了避免这种情况,可以使用深拷贝,完全复制对象及其引用类型的字段。

2.1 深拷贝的实现
cs 复制代码
public class Address
{
    public string Street { get; set; }
    public string City { get; set; }

    public Address(string street, string city)
    {
        Street = street;
        City = city;
    }
}

public class Person : IPrototype
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Address Address { get; set; }

    public Person(string name, int age, Address address)
    {
        Name = name;
        Age = age;
        Address = address;
    }

    // 深拷贝
    public IPrototype Clone()
    {
        // 创建新的 Person 实例,并手动克隆 Address 属性
        Person clonedPerson = (Person)this.MemberwiseClone();
        clonedPerson.Address = new Address(this.Address.Street, this.Address.City);
        return clonedPerson;
    }

    public void DisplayInfo()
    {
        Console.WriteLine($"Name: {Name}, Age: {Age}, Address: {Address.Street}, {Address.City}");
    }
}
2.2 使用深拷贝的客户端代码
cs 复制代码
class Program
{
    static void Main(string[] args)
    {
        // 创建原型对象,包含引用类型 Address
        Address address1 = new Address("123 Main St", "CityA");
        Person person1 = new Person("Alice", 30, address1);
        person1.DisplayInfo();

        // 使用深拷贝克隆一个新的对象
        Person person2 = (Person)person1.Clone();
        person2.Name = "Bob"; // 修改克隆对象的属性
        person2.Age = 25;
        person2.Address.Street = "456 Elm St"; // 修改克隆对象的地址
        person2.DisplayInfo();

        // 确认原型对象的 Address 未改变
        person1.DisplayInfo();
    }
}

输出:

cs 复制代码
Name: Alice, Age: 30, Address: 123 Main St, CityA
Name: Bob, Age: 25, Address: 456 Elm St, CityA
Name: Alice, Age: 30, Address: 123 Main St, CityA

在这个深拷贝示例中,Address 是一个引用类型字段。在 Clone() 方法中,我们手动创建了一个新的 Address 实例,确保 person2Address 被完全复制,避免了原型对象和克隆对象共享同一个 Address 实例。

3. 总结

  • 浅拷贝 :通过 MemberwiseClone() 实现,适用于没有引用类型字段或引用类型字段不需要独立拷贝的场景。
  • 深拷贝:手动克隆引用类型字段,确保克隆对象和原型对象的所有字段都完全独立。
  • 原型模式的优点是避免了重复构建对象的复杂性,尤其在需要频繁创建相似对象的场景中非常有用。

这种模式适用于创建对象时,性能和资源是一个重要考虑的因素,或者对象创建过程非常复杂的情况。

相关推荐
bugcome_com10 小时前
零基础入门C#:一篇搞懂核心知识点
c#
J_liaty14 小时前
23种设计模式一代理模式
设计模式·代理模式
程序员敲代码吗14 小时前
如何通过命令行启动COMSOL的参数化、批处理和集群扫描
java·c#·bash
缺点内向16 小时前
C#: 告别繁琐!轻松移除Word文档中的文本与图片水印
c#·自动化·word·.net
喵叔哟16 小时前
06-ASPNETCore-WebAPI开发
服务器·后端·c#
2501_9307077817 小时前
使用 C# .NET 从 PowerPoint 演示文稿中提取背景图片
c#·powerpoint·.net
初级代码游戏17 小时前
套路化编程 C# winform 自适应缩放布局
开发语言·c#·winform·自动布局·自动缩放
大空大地202618 小时前
流程控制语句--switch多分支语句使用、while循环语句的使用、do...while语句、for循环
c#
方见华Richard19 小时前
世毫九实验室(Shardy Lab)研究成果清单(2025版)
人工智能·经验分享·交互·原型模式·空间计算
苏渡苇20 小时前
优雅应对异常,从“try-catch堆砌”到“设计驱动”
java·后端·设计模式·学习方法·责任链模式