7

保持类松散耦合是编写易于理解、修改和调试的代码的一个重要方面——我明白这一点。然而,作为一个新手,几乎任何时候我都会超越我所苦苦挣扎的最简单的例子。

我或多或少地了解如何将字符串、整数和简单数据类型封装在它们自己的类中。然而,当我开始处理诸如富文本格式之类的信息时,事情变得非常复杂——除非我只使用组件中已经存在的各种方法。继续这个例子,假设我正在编写一些在 UI 中包含 RTF 备忘录组件的东西。在 Delphi 中,该组件具有用于执行诸如保存格式化文本之类的内置方法。此外,有时似乎唯一(或至少是最好的)处理 RTF 文本本身的方法是通过再次内置到组件中的方法。

当我已经有一个组件为我完成所有这些工作时,我将如何(或为什么)在另一个类中完成保存、加载和格式化文本的所有工作?

就我自己而言,我通常最终要么 (a) 做一些看起来比需要复杂得多的事情,重新发明已经存在的方法,或者 (b) 创建仍然彼此紧密耦合的糟糕的类。正如他们在非正式广告中所说的那样,“必须有更好的方法!”

我只是在概念上迷失了“更好的方式”是如何工作的。有什么想法吗?

4

4 回答 4

5

我会建议两个概念,接口和依赖注入,作为解耦类的一种方式。接口为您提供了一种定义独立于任何实现的契约或一组预期行为的方法。当你有一个类依赖于一个接口而不是一个类时,你可以自由地替换实现该接口的其他类,而不必重写依赖于它的类。

当您使用具有依赖注入的接口时,即为类提供它要处理的实际实现而不是让它自己创建特定的实现,您可以在应用程序中实现更多的解耦。现在这个类只知道接口,甚至不知道如何创建它,只是使用它。依赖注入通常与创建模式(例如 Builder 或 Factory)一起使用,在这些模式中,您将对象的构造本地化在单个类中,以便在使用其他类扩展应用程序时只需要更改该类。

另外,请记住耦合(及其孪生兄弟内聚)是一种相对度量。您无法消除所有耦合,否则您的对象将无法交互。有一定程度的依赖是必要的。您还需要平衡它与易用性和实施​​。

至于您的特定示例,没有实际代码很难说。我怀疑您过度设计了解决方案并违反了 DRY 原则(不要重复自己)。您可能需要研究使用接口的方法,也许还需要一个轻量级包装器来将您的类与框架组件分离,而不是完全重新实现。

于 2009-03-27T18:24:35.100 回答
5

我相信你错过了一些基本概念。

OOP背后的想法始于离散的、可重用的逻辑单元。强调创建自给自足的模块。

对于 RTF 备忘录组件,它通过处理给定的一组数据(备忘录)来满足上述标准,这样您的程序和程序中的其他对象就不会关心它是如何工作的。它的目的是显示一个界面,接受数据,操作该特定数据,并将该数据传递给程序的另一部分。

松散耦合背后的想法很简单,就是您可以用另一个满足相同接口规范的控件替换该备忘录控件。也就是说,您可以实例化它,让用户与之交互,并在必要时提取数据。

松散耦合与关注点分离(SoC) 的理念密不可分;这是将程序分解为不同功能以减少重叠功能并使管理更容易的过程。但它们不是一回事。顺便说一句,这也是从程序化编程风格转向 OOP 背后的主要驱动力之一。由于 OOP 迫使编程根据相关和离散的功能进行思考。

听起来你真的在问 SoC。

实现SoC的方法有很多。有时它涉及将 UI、处理逻辑和持久层分开(例如,考虑 MVC 设计模式)。有时只是将相关功能放在一起以降低复杂性;RTF 控件已经通过包含操作数据所需的所有函数来实现这一点,这样您就没有进一步的依赖关系。

于 2009-03-27T18:30:05.680 回答
0

好吧,我对这个问题并不完全清楚,但似乎策略模式在这里可以工作。

基于您的父 RTF 对象构建一个对象,但将用于存储等的处理方法设置为具有自己方法的已定义对象。

这可以在不严格继承所有父方法的情况下启用组合功能,并且您不必构建巨大的自定义对象,只需替换您需要的方法即可。

于 2009-03-27T18:11:35.757 回答
0

您选择的示例相当复杂。

当您说 rtf 备忘录组件非常松散耦合时,您是对的。如此松散,以至于它实际上是不可扩展的,并且只能按原样使用,因为它集成了表示/视图、控制器和模型。

如果您想查看设计良好、可扩展的富文本系统的示例,请查看OS X 文本系统(或 Gnustep,如果您想阅读代码)的文档。它很复杂,因为需要做出很多设计决策,并且需要从一个模块隐藏到另一个模块。在那里,您可以直接以良好的结构工作。

rtf memo 组件的使用范围有限,您可能必须使用设计良好的类来解决这个问题:

  • 仅当您不必将程序中的其他数据保存在同一文件/数据库中时,组件数据的加载和保存才有意义。
  • 它也不能很好地处理大量数据。
  • 而且它只理解 rtf 的一小部分。
于 2009-03-27T22:57:03.747 回答