CodeGym /Java 课程 /模块 3 /如何松散软件模块之间的耦合

如何松散软件模块之间的耦合

模块 3
第 14 级 , 课程 7
可用

8.1 分解就是一切

为了清楚起见,一张来自一篇好文章“面向对象系统的解耦”的图片说明了将要讨论的要点。

分解

您还认为设计应用程序架构很容易吗?

8.2 接口,实现隐藏

降低系统耦合度的主要原则是OOP的原则以及其背后的封装+抽象+多态的原则。

因此:

  • 模块应该是彼此的“黑盒子”(封装)。这意味着一个模块不应该“爬升”到另一个模块并且不知道它的内部结构。一个子系统中的对象不应该直接访问另一个子系统中的对象。
  • 模块/子系统应该仅通过接口(即不依赖于实现细节的抽象)相互交互。因此,每个模块必须有一个或多个定义良好的接口,用于与其他模块交互。

“黑盒”(封装)原则允许我们独立于其他子系统来考虑每个子系统的结构。该模块是一个“黑盒子”,可以相对自由地更改。问题只会出现在不同模块(或模块和环境)的交界处。

而这个交互必须用最一般(抽象)的形式来描述,也就是用接口的形式。在这种情况下,代码将与任何符合接口契约的实现一样工作。正是这种通过称为多态性的统一接口与不同的实现(模块或对象)一起工作的能力。

这就是为什么Servlet 是一个接口:Web 容器对 servlet 一无所知,因为这些是一些实现 Servlet 接口的对象,仅此而已。Servlets 也知道一点容器的结构。Servlet 接口是使 Java Web 应用程序接管世界所需的契约、标准和最小交互。

多态性根本不是方法的重写,就像有时被错误地认为的那样,但首先是具有相同接口或“一个接口,许多实现”的模块/对象的互换性。实现多态,根本不需要继承机制。理解这一点很重要,因为通常应尽可能避免继承

得益于接口和多态性,正是实现了在不改变已经编写的内容的情况下修改和扩展代码的能力(开闭原则)。

只要模块的交互完全以接口的形式描述并且不依赖于特定的实现,您就有机会绝对“无痛地”为系统用实现相同接口的任何其他模块替换一个模块,以及添加一个新的,从而扩展功能。

就像在 LEGO 构造器中一样 - 接口标准化了交互,并充当了一种连接器,可以连接任何具有合适连接器的模块。

设计人员的灵活性得到保证,因为我们可以简单地将一个模块或部件替换为具有相同连接器(具有相同接口)的另一个模块或部件,以及添加我们喜欢的任意数量的新部件(同时,现有的零件不会以任何方式改变或改变)。

接口允许您构建一个更简单的系统,将每个子系统视为一个整体并忽略其内部结构。它们允许模块进行交互,同时对彼此的内部结构一无所知,从而充分贯彻了最少知识原则,这是松散耦合的基础。

定义的接口越通用/抽象,它们对交互施加的限制越少,系统就越灵活。从这里开始,实际上遵循了 SOLID 的另一个原则——接口隔离原则,它反对“厚接口”。

他说,大而笨重的接口应该被分解成更小、更具体的接口,这样小接口(依赖模块)的客户只知道他们需要使用的方法。

该原则表述如下:“客户不应依赖他们不使用的方法(注意方法)”或“许多专用接口优于一个通用接口”。

事实证明,只有借助于接口,即抽象来描述模块之间的交互和依赖关系,而无需使用有关其内部结构和结构的知识,才能提供弱连接,实际上实现了封装。另外,我们有能力通过添加和使用不同的实现来扩展/改变系统的行为,也就是说,由于多态性。是的,我们又来到了OOP——封装、抽象、多态。

8.3 Facade:模块接口

这里有经验的程序员会问:如果不是在对象层面设计,而是在模块层面设计,那么模块接口的实现是什么?

答:用设计模式的语言来说,那么可以有一个专门的对象来负责模块接口的实现——Facade。如果您在包含 Gateway 后缀(例如,MobileApiGateway)的对象上调用方法,那么它很可能是一个外观。

外观是一个接口对象,它积累了一组用于处理某个子系统的高级操作,隐藏了其内部结构和真正的复杂性。针对子系统实现中的更改提供保护。作为一个单一的入口点——“你踢门面,他知道谁需要踢这个子系统才能得到他需要的东西。”

您刚刚了解了最重要的设计模式之一,它允许您在设计模块时使用接口的概念,从而将它们解耦——“Facade”。

此外,“Facade”使得以与处理普通对象相同的方式处理模块成为可能,并在设计模块时应用类设计中使用的所有有用原则和技术。

门面:模块接口

注意:虽然大多数程序员在设计类(对象)时都了解接口的重要性,但似乎许多人也发现了在模块级别使用接口的想法。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION