IRONSOFTWAREHOME

C#接口松散耦合 — 通过Tim Corey(第16课)解释

C#应用从头到尾第16课——创建锦标赛表单部分2

Tim Corey

44m 47s

在课程"C#应用从头到尾"的第16课中,Tim Corey继续构建创建锦标赛表单,但真正的学习目标远不止连接按钮和列表框。 随着Tim完成表单的连接,他在C#中引入了一个核心软件设计概念:用于松耦合的接口。 这节课显示接口不仅仅是一个抽象的学术概念,而是一个实用的工具,用于解决WinForms应用程序中的实际问题。

在这篇文章中,我们深入研究Tim Corey如何解释接口,为什么使用它们,以及它们如何帮助避免紧耦合。 所有的解释、推理和结论都直接来自Tim的演练,使用他的流程、术语和脚本中的示例。

连接表单很简单 — 正确连接它们并不简单

在1:18,Tim开始连接创建奖品和创建团队的UI元素。 他立即指出,这一步可以感觉很吓人,不是因为调用另一个表单很难,而是因为正确获取数据时人们通常会犯错误。

Tim解释说,挑战不是打开另一个表单——那部分很简单。 挑战是如何在不造成长期设计问题的情况下,让一个表单回到另一个表单。 此时,定义合约而不是依赖关系的理念开始变得重要。

紧耦合的诱惑

大约在1:34,Tim明确指出一个常见错误:直接把创建锦标赛表单与创建奖品表单联系在一起。 在这种方法中,一个类确切地知道它在与哪个其他类交谈。

Tim解释这会导致紧耦合,意味着表单直接依赖于彼此。 如果一个表单更改,另一个表单会受到影响。 如果程序的另一个部分后来想要同样的功能,它不能重用它。

他强调,尽管这可能编译并工作,但这不是一个良好的长期设计选择,尤其是在更大的系统或专业环境中。

在编写代码之前考虑步骤

在2:02,Tim停下来,写下步骤而不是直接进入编写代码。 他列出:

  1. 调用创建奖品表单

  2. 返回一个PrizeModel

  3. 将其添加到选定的奖品列表中

Tim解释,先写下步骤有助于避免逻辑错误,并使代码的意图清晰。 这种结构化思维在引入接口后变得尤为重要,因为接口定义了必须发生的事情,而不是如何发生。

引用类型以及为何返回值并非总是必要的

大约在4:56时,Tim解释了模型传递的一个重要细节。 他提醒观众,他们正在传递地址,而不是对象的副本。

当通过数据连接器保存奖品时,模型已经填充了其ID。 Tim指出重新返回模型通常是不必要的,因为实例已经被修改。

这进一步说明了为何接口不用于盲目地移动数据——它们用于显示完成和责任,而不是重复。

首先传递模型为何是个坏主意

在6:42,Tim讨论了将PrizeModel传入表单构造函数以便两个表单共享同一实例的想法。

他解释了为何在实际使用中失败:如果用户取消表单,您的列表中会出现一个空的或无效的奖品。Tim展示了仅因为两个类可以共享实例数据并不意味着它们应该这样做。

这个时刻进一步强调了接口定义行为而不是数据存储的概念。

直接传递调用表单更加糟糕

大约在7:46,Tim谈到了另一种常见方法:将整个创建比赛表单传入创建奖品表单并调用如SavePrize的公共方法。

Tim解释说这更糟糕的原因是:

  • 奖品表单现在确切知道哪个类在调用它

  • 其他不相关的类无法复用奖品表单

  • 这个类被限定于一个用例

他明确指出这是紧耦合,而这是我们要避免的。

介绍作为契约的接口

在9:01,Tim引入了解决方案:一个接口。

他使用interface关键字创建了一个新的接口,并命名为IPrizeRequester。 Tim提醒观众,接口:

  • 不是一个类

  • 不包含具体方法

  • 用于定义契约

该接口包含一个方法:

  • PrizeComplete(PrizeModel model)

Tim解释说这方法定义了必须发生的事情,而不是如何发生。

接口成员和责任

在9:40,Tim解释道,无论谁实现这个接口,都同意支持该方法。 接口默认拥有公共成员,它不声明实例数据。

这是Tim明确指出接口定义能力而不是存储的地方。 实现类决定在调用方法时要做什么。

传递接口类型而不是类

在10:19,Tim 修改了创建奖品表单构造函数以接受一个IPrizeRequester而不是具体表单。

他解释说这意味着:

  • 会有人调用表单

  • 表单不知道那是谁

  • 唯一的要求是调用者实现了接口

这就是实际中的松耦合。奖品表单依赖于接口类型,而不是特定的类。

存储接口实例以供以后使用

在11:06,Tim在类级别存储接口实例。 他解释说构造函数参数仅在构造函数内部存在,除非存储它们。

这允许奖品表单随后从按钮单击事件内调用PrizeComplete。

回调实现类

在11:49,Tim展示了关键时刻:

callingForm.PrizeComplete(model);
Text

他解释说奖品表单现在回调用实现接口的人,并传达说:

"我完成了,这是完成的模型。"

只有在此调用之后,表单才关闭。 这确保只有在创建成功时才添加奖品。

在比赛表单中实现接口

在13:29,Tim切换到创建比赛表单并实现接口。

在13:58,他解释了this关键字,将其描述为当前实例——内存中的实际对象。 通过传递this,表单在通过接口契约移交其地址。

多个接口,一个类

在18:41,Tim介绍了第二个接口:ITeamRequester。

他解释说,虽然一个类只能继承一个基类(比如Form),但它可以实现多个接口。 这允许单个类支持多个不相关的行为,而无需多重继承。

Tim强调接口不带入代码——它们只定义必需的方法。

模式、一致性和错误检测

靠近42:08,Tim反思为何使用模式很重要。 重复相同的基于接口的结构使漏掉的步骤显而易见且调试更容易。

Tim鼓励写下东西,使用一致的模式,而不是试图将一切都放在脑海中。 据他说,好的设计不是关于完美,而是关于清晰性、结构性以及使未来的更改更容易。

结论

在第16课中,Tim Corey使用一个真实的WinForms用例来展示接口如何实现松耦合。 而不是依赖于抽象的例子,他展示了接口如何:

  • 定义契约

  • 解耦类

  • 支持单个类中的多个接口

  • 防止紧耦合

  • 提高长期的灵活性

到课程结束时,应用程序不仅可以工作——它被结构化为支持成长、重用和清晰。 Tim的方法使接口在真实世界的C#开发中感觉务实、有目的和必不可少。

要完整、端到端地应用这些接口和松耦合概念,请观看完整的第16课视频,其中每一步都在工作中的C#应用程序内实现、测试和完善。

Earn More by Sharing What You Love

Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Let's Stay in Touch!

Join our newsletter, you’ll get exclusive access on article updates. We value your privacy

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户