C# 中的原型设计模式

2025 年 2 月 5 日 | 阅读 6 分钟

关于原型设计模式?

GoF 定义的原型设计模式,通过一个原型实例来确定应创建的对象的类型,并通过复制该原型来生成其他对象。

在 C# 中,原型设计模式是一种创建型模式,用于通过复制已有的对象或原型来创建对象。当创建对象的成本很高或其复杂性高于复制现有对象时,此模式尤其有用。

简单来说,原型设计模式允许我们从一个已有的类对象创建副本或新对象。换句话说,它通过克隆原始对象及其数据来创建新对象。

我们对新克隆的项所做的任何修改都不会影响原始对象。

示例

在 C# 中,当我们尝试使用赋值运算符 (=) 将一个对象复制到另一个对象时,两个对象共享相同的内存地址。这是因为赋值运算符 (=) 复制的是引用而不是对象,除非存在值类型字段。为了更好地理解,请看附图。

Prototype Design Pattern in C#

上图说明我们有一个名为 employee 的类,它有两个属性:Name 和 Department。接下来,我们将当前的 employee 对象(即 emp1)赋值给一个新的 employee 实例(即 emp2)。

因此,请记住,赋值运算符 (=) 应仅用于按引用传递。下面是完整的代码示例。

C# 中的对象克隆是什么?

当我们讨论 C# 对象克隆时,我们指的是按值传递。因此,修改一个对象不会影响另一个对象。让我们研究一下如何将一个对象复制到另一个对象。C# 中一种称为 MemberwiseClone 的技术可用于实现此目的;它会创建一个新对象,并完整复制该对象,并分配不同的内存。请看下图以更好地理解。

Prototype Design Pattern in C#

如上图所示,我们在 employee 类中创建了一个名为 GetClone 的方法。在该过程中,我们使用 MemberwiseClone 函数返回一个克隆对象。然后使用 GetClone 函数来构建第二个实例,该函数生成 emp1 对象的一个全新、完整克隆。由于此时两个对象(即 emp1 和 emp2)是独立的,因此我们对其中一个对象所做的任何更改都不会影响另一个对象。

请注意,使用 MemberwiseClone() 函数时,对象是浅拷贝。如果你的对象包含其他对象,并且你想要深拷贝(即使是内部对象也被复制),那么你需要向 Clone() 函数添加额外的逻辑。

关于 C# MemberwiseClone 方法需要牢记的重要事项

  • MemberwiseClone 函数包含在 System.Object 类中,并生成对给定对象的粗略副本。
  • 如果字段是值类型,复制过程将按位复制字段。
  • 现在我们对对象克隆有了更好的理解,让我们学习如何在 C# 中使用它来应用原型设计模式。

C# 中原型设计模式的用例

当创建的对象必须与现有对象相似,或者克隆对象比使用普通构造函数更有效地创建对象时,原型模式就派上用场了。此模式通常用于创建新类实例对性能有重大影响的情况,例如加载模板。

理解 C# 中原型设计模式的实际示例

正如我们所讨论的,为了提高应用程序的效率,我们在 C# 中使用原型设计模式来从现有对象创建副本或克隆对象。这表明,在创建昂贵或复杂的对象时,我们必须使用原型设计模式。

例如,在花费了数据库活动成本后,您可能需要创建一个对象。然后,如果我们将对象缓存起来,在后续请求时返回其克隆,并在需要时更新数据库,就可以减少我们应用程序和数据库之间的数据库连接。因此,性能将得到提高。

让我们继续并逐步在 C# 中实现原型设计模式。实现原型设计模式后,我们将查看 UML 图,并将示例与 UML(或类)图进行比较。因此,请将以下代码复制并粘贴到您刚刚创建的 employee.cs 类文件中。

因此,创建一个名为 Permanentemployee.cs 的类文件,并将以下代码插入其中。我们在 GetClone 函数中创建了创建当前对象浅拷贝的逻辑。

接下来,将以下代码复制并粘贴到名为 Temporaryemployee.cs 的类文件中。如您所见,该类实现了 employee 抽象类以及两个抽象方法。我们在 GetClone 函数中创建了创建当前对象浅拷贝的逻辑。

有必要在客户端代码中验证 Clone 方法是否按预期工作。在我们的示例中,Programme 类的主函数只做了客户端的工作。因此,请对 Programme 类的 Main 方法进行以下修改。

原型设计模式 UML(类)图

在审查了 C# 中的原型设计模式实现后,让我们尝试实现相应的 UML(统一建模语言)或类图。为了更好地理解,请参考附图,它显示了原型布局设计的不同组件。

为了帮助您理解原型设计模式的各个组成部分,我包含了一个 UML 图和我们的示例之间的比较。

让我们详细检查原型设计模式的每个部分

  • 将作为原型的接口或抽象类,用于各种可被复制的对象类型。
  • 客户端 (Client): 请求原型复制自身以创建新对象的类称为客户端。

原型模式的优点

  • 避免昂贵的创建: 这在创建新对象比复制旧对象成本更高或更复杂的情况下很有用。
  • 捕获复杂性: 原型捕获了制造产品的复杂性和细节。

何时使用?

C# 中的原型设计模式在以下场景中特别有用:

  • 昂贵的对象创建: 您已经有一个与所需对象相似的对象,因此创建类需要时间和资源。
  • 避免子类化: 当您需要创建与现有对象相似的对象,但又想避免子类化层次结构的麻烦时。
  • 动态系统配置: 如果您需要一个动态系统,可以在运行时通过复制预定义的原型来创建新的对象类型,那么这就是要使用的配置。
  • 保留初始状态: 在需要记录和保存对象状态以便以后复制或恢复的情况下。
  • 最小化数据库调用: 在检索对象状态需要大量数据库操作的情况下,原型可以通过复制先前加载的对象来最小化数据库调用。
  • 复杂的对象克隆: 原型模式提供了一种简单的方法来深拷贝或克隆复杂的对象,特别是当这些对象包含复杂的结构或循环引用时。
  • 对象填充: 当需要大量相同的对象时,复制原型比从头开始更有效。

浅拷贝与深拷贝

浅拷贝: 在 C# 中,使用 MemberwiseClone 方法进行浅拷贝。它将对象字段的值传输到新对象。

深拷贝: 深克隆的过程包括复制字段引用的对象。

虽然深拷贝涉及不仅复制对象本身,还复制其引用的所有对象,而浅拷贝则创建了一个新对象。原型设计模式是 C# 开发工具箱中一个有用的工具,可以有效地处理对象创建,并保持代码的可伸缩性和灵活性。

结论

总而言之,C# 原型设计模式提供了一种灵活的方法,通过复制现有对象来创建新对象。它抽象了对象创建过程,使得无需依赖构造函数或初始化逻辑即可轻松创建新对象。通过在应用程序中实现原型模式,您可以重用现有对象并通过克隆节省对象创建操作的成本。

通过将客户端代码与要实例化的具体类分离,此技术还可以提高代码的灵活性和可维护性。如果您正在使用 C# 实现原型设计模式,请考虑深拷贝还是浅拷贝更适合您的用例。


下一个主题Quantifiers-in-c-sharp