【问题标题】:What is "loose coupling?" Please provide examples什么是“松散耦合”?请提供例子
【发布时间】:2010-09-18 14:59:51
【问题描述】:

我似乎无法理解“松散耦合”的概念。我想“松散”这个词通常带有负面含义并没有帮助,所以我总是忘记松散耦合是一件的事情。

有人请展示一些“之前”和“之后”的代码(或伪代码)来说明这个概念吗?

【问题讨论】:

  • 我不确定如何将其与特定语言分开,因为部分概念是如何使用一种语言来防止代码单元相互纠缠。我还注意到,一些答案使用代码来说明这个概念。
  • 完全不同意,不同的语言可以用不同的方式说明实用性,在动态语言和编译语言中尤其明显。但无论哪种方式,概念都是相同的。
  • 松与紧耦合与去耦合。跟风总是不是一件好事,有时好/有时不好......我们应该有自己的独立,所以班级也应该这样做。

标签: oop language-agnostic loose-coupling


【解决方案1】:

考虑一个简单的购物车应用程序,它使用CartContents 类来跟踪购物车中的物品,并使用Order 类来处理购买。 Order 需要确定购物车中内容的总价值,它可能会这样做:

紧耦合示例:

public class CartEntry
{
    public float Price;
    public int Quantity;
}

public class CartContents
{
    public CartEntry[] items;
}

public class Order
{
    private CartContents cart;
    private float salesTax;

    public Order(CartContents cart, float salesTax)
    {
        this.cart = cart;
        this.salesTax = salesTax;
    }

    public float OrderTotal()
    {
        float cartTotal = 0;
        for (int i = 0; i < cart.items.Length; i++)
        {
            cartTotal += cart.items[i].Price * cart.items[i].Quantity;
        }
        cartTotal += cartTotal*salesTax;
        return cartTotal;
    }
}

注意OrderTotal 方法(以及Order 类)如何依赖于CartContentsCartEntry 类的实现细节。如果我们要尝试更改此逻辑以允许折扣,我们可能必须更改所有 3 个类。此外,如果我们改为使用 List&lt;CartEntry&gt; 集合来跟踪项目,我们也必须更改 Order 类。

现在这里有一个更好的方法来做同样的事情:

较少耦合的例子:

public class CartEntry
{
    public float Price;
    public int Quantity;

    public float GetLineItemTotal()
    {
        return Price * Quantity;
    }
}

public class CartContents
{
    public CartEntry[] items;

    public float GetCartItemsTotal()
    {
        float cartTotal = 0;
        foreach (CartEntry item in items)
        {
            cartTotal += item.GetLineItemTotal();
        }
        return cartTotal;
    }
}

public class Order
{
    private CartContents cart;
    private float salesTax;

    public Order(CartContents cart, float salesTax)
    {
        this.cart = cart;
        this.salesTax = salesTax;
    }

    public float OrderTotal()
    {
        return cart.GetCartItemsTotal() * (1.0f + salesTax);
    }
}

特定于购物车订单项或购物车集合或订单实施的逻辑仅限于该类。因此,我们可以更改任何这些类的实现,而无需更改其他类。我们可以通过改进设计、引入接口等来进一步解耦,但我认为你明白了这一点。

【讨论】:

  • 您能否扩展答案,通过依赖注入引入进一步解耦(尽管构造函数应该是理想的)?
  • @Wedge,我认为Order 没有理由知道Cart。现场购物和制造是两个不同的背景。当客户准备好付款时,您可以有一个流程负责将 CartEntries 翻译成对Order 有意义的东西。这样Order 类也可以在没有Cart 的情况下被实例化和使用。
  • @Wedge 你能回复我的评论吗?
  • 很好&简单的解释。我开始在“..注意 OrderTotal 方法(以及 Order 类)如何依赖于 CartContents 和 CartEntry 类的实现细节。”
  • @JoSo, However in these days, more and more architects agree that this overly object-oriented style is bad practice [需要引用] :)
【解决方案2】:

许多集成产品(尤其是 Apple),例如 iPodsiPads 是紧密耦合的一个很好的例子:一旦电池没电了,您不妨购买新设备因为电池是焊接固定的,不会松动,因此更换起来非常昂贵。松散耦合的播放器可以轻松更换电池。

软件开发也是如此:通常(很多)使用松散耦合的代码来促进扩展和替换(并使各个部分更容易理解)。但是,在极少数情况下,在特殊情况下紧密耦合可能是有利的,因为多个模块的紧密集成可以实现更好的优化。

【讨论】:

  • 松耦合好还是紧耦合好?如何决定实现松耦合还是紧耦合?
  • 感谢这个很好的例子。我花了很多时间在其他答案上,但不值得这样
  • Sreekanth Karumanaghat,您是宁愿花更少的钱买一个电池,然后又拥有一个工作正常的 iPod,还是宁愿花很多钱买一个完整的 iPod?
  • @SreekanthKarumanaghat 通常松散耦合更好,因为它促进了模块化,从而使代码更易于维护。如果您将类/库/代码紧密耦合,那么您在一个类中所做的任何小改动都必须在所有使用它的类中实现。
【解决方案3】:

我将使用 Java 作为示例。假设我们有一个如下所示的类:

public class ABC
{
   public void doDiskAccess() {...}
}

当我打电话给班级时,我需要做这样的事情:

ABC abc = new ABC();

abc. doDiskAccess();

到目前为止,一切都很好。现在假设我有另一个看起来像这样的类:

public class XYZ
{
   public void doNetworkAccess() {...}
}

它看起来与 ABC 完全相同,但假设它通过网络而不是磁盘工作。所以现在让我们编写一个这样的程序:

if(config.isNetwork()) new XYZ().doNetworkAccess();
else new ABC().doDiskAccess();

这行得通,但有点笨拙。我可以用这样的界面来简化它:

public interface Runnable
{
    public void run();
}

public class ABC implements Runnable
{
   public void run() {...}
}

public class XYZ implements Runnable
{
   public void run() {...}
}

现在我的代码如下所示:

Runnable obj = config.isNetwork() ? new XYZ() : new ABC();

obj.run();

看看这有多简洁易懂?我们刚刚理解了松耦合的第一个基本原则:抽象。这里的关键是确保 ABC 和 XYZ 不依赖于调用它们的类的任何方法或变量。这使得 ABC 和 XYZ 成为完全独立的 API。或者换句话说,它们与父类“解耦”或“松耦合”。

但是如果我们需要两者之间的通信呢?好吧,那么我们可以使用像 Event Model 这样的进一步抽象来确保父代码永远不需要与您创建的 API 耦合。

【讨论】:

  • 这个例子还是有相当高的耦合度的。刚才不是耦合到一个类,而是有两个可供选择。此示例假定只有两个“可运行”实现可用。在这种情况下,甚至不需要接口。
  • 这些 Run* 和 Do* 命名的方法对我来说是一种巨大的代码气味。您不妨将其重构为使用 IHandleStuff 或 IFrobnicateThings。在这种情况下,Runnable 是一个过于笼统的术语。
  • 欧文,亲爱的朋友。如果他不了解耦合,他将如何了解工厂模式给他带来的好处?这个代码示例使他走上了正轨。目的是让他更好地理解问题并实现如何抽象出对象的创建。
  • 如果将 ABC 和 XYZ 重命名为 DiskAccessorNetworkAccessor 之类的名称,这会更易读吗?我不知道没有 java ...
【解决方案4】:

抱歉,“松散耦合”不是编码问题,而是设计问题。 “松耦合”一词与“高内聚”的理想状态密切相关,相反但互补。

松散耦合仅仅意味着应该构建单独的设计元素,从而减少他们需要了解的关于其他设计元素的不必要信息量。

高内聚有点像“紧耦合”,但高内聚是一种状态,其中真正需要相互了解的设计元素被设计成能够干净优雅地协同工作。

关键是,一些设计元素应该知道其他设计元素的细节,所以它们应该这样设计,而不是偶然。其他设计元素不应该知道其他设计元素的细节,所以应该有目的地这样设计,而不是随意设计。

实现这一点留给读者练习:)。

【讨论】:

    【解决方案5】:

    紧密耦合的代码依赖于具体的实现。如果我需要我的代码中的字符串列表并像这样声明它(在 Java 中)

    ArrayList<String> myList = new ArrayList<String>();
    

    那我就依赖 ArrayList 的实现了。

    如果我想将其更改为松散耦合的代码,我将引用设为接口(或其他抽象)类型。

    List<String> myList = new ArrayList<String>();
    

    这使我无法在 myList 上调用特定于 ArrayList 实现的 any 方法。我仅限于 List 接口中定义的那些方法。如果我稍后决定我真的需要一个 LinkedList,我只需要在我创建新 List 的一个地方更改我的代码,而不是在我调用 ArrayList 方法的 100 个地方。

    当然,您可以使用第一个声明实例化一个 ArrayList,并限制自己不使用任何不属于 List 接口的方法,但是使用第二个声明会使编译器保留您诚实。

    【讨论】:

    • 这与“耦合”实际上是什么几乎没有关系。请参阅stackoverflow.com/questions/39946/coupling-and-cohesion 以获得一些好的答案。
    • @Rogerio:我认为这有关系。也许您对“耦合”的其他定义感到困惑,但您应该阅读Loose coupling。 “当依赖类包含直接指向提供所需行为的具体类的指针时会发生强耦合......当依赖类仅包含指向接口的指针时会发生松散耦合,然后可以由一个或多个具体类实现。”在我的示例中,我的代码将通过 List 接口松散耦合到 ArrayList。
    • @Bill:感谢您的链接,但那篇文章对我来说似乎完全是假的。它似乎“重新解释”了另一个领域(组织行为)的想法,给出了与 Larry Constantine 最初的软件特定定义相矛盾的“松散耦合”定义:en.wikipedia.org/wiki/Coupling_(computer_science)
    • @Rogerio:康斯坦丁的论文写于 1974 年。在过去的 36 年中,可能进行了很多重新解释,但我不认为维基百科的文章是它的来源。例如,Dependency Injection 之类的模式依赖于接口来松散耦合,正如我在回答中所描述的那样。
    • @Bill:当然,Constantine 在结构化设计方面的工作已经过时了,但我看不出有任何理由来否定或彻底重新解释它。内聚和耦合的原始概念是面向对象设计的核心,就像继承和多态一样。 DI(更好的文章是martinfowler.com/articles/injection.html)只是一种用于插件外部配置的技术(抽象接口,在运行时通过配置代码选择实现);另一种这样的技术是服务定位器模式。 DI 和耦合是独立的概念。
    【解决方案6】:

    这里答案之间的差异程度说明了为什么这是一个难以掌握的概念,但要尽可能简单地描述它:

    为了让我知道如果我把球扔给你,那么你可以接住它,我真的不需要知道你多大了。我不需要知道你早餐吃了什么,我真的不在乎你的初恋是谁。我只需要知道你能抓到。如果我知道这一点,那么我不在乎是你我在向你或你的兄弟扔球。

    对于像 c# 或 Java 等非动态语言,我们通过接口来实现这一点。假设我们有以下接口:

    public ICatcher
    {
       public void Catch();
    }
    

    现在假设我们有以下类:

    public CatcherA : ICatcher
    {
       public void Catch()
       {
          console.writeline("You Caught it");
       }
    
    }
    public CatcherB : ICatcher
    {
       public void Catch()
       {
          console.writeline("Your brother Caught it");
       }
    
    }
    

    现在CatcherACatcherB 都实现了Catch 方法,因此需要Catcher 的服务可以使用其中任何一个,而不必真正在乎到底是哪一个。所以一个紧密耦合的服务可能会直接实例化一个被捕获的即

    public CatchService
    {
       private CatcherA catcher = new CatcherA();
    
       public void CatchService()
       {
          catcher.Catch();
       }
    
    }
    

    所以CatchService 可能完全按照它的计划去做,但它使用CatcherA 并且始终使用CatcherA。它是硬编码的,所以它会一直留在那里,直到有人出现并对其进行重构。

    现在让我们采用另一个选项,称为依赖注入:

    public CatchService
    {
       private ICatcher catcher;
    
       public void CatchService(ICatcher catcher)
       {
          this.catcher = catcher;
          catcher.Catch();
       }
    }
    

    因此,实例化 CatchService 的调用可能会执行以下操作:

    CatchService catchService = new CatchService(new CatcherA());
    

    CatchService catchService = new CatchService(new CatcherB());
    

    这意味着Catch 服务没有与CatcherACatcherB 紧密耦合。

    还有其他几种松散耦合服务的策略,例如使用 IoC 框架等。

    【讨论】:

    • 我比其他例子更喜欢这个例子,因为这种事情每天都在商业世界中发生。如果 Class Person 运行,Class Cat 运行,Class Dog 运行等等。这将是一个庞大的程序来详细说明所有这些运行的类。但是使用一个叫做runs的接口,每个类都做同样的事情,让你的程序更加灵活和易于管理。 :)
    • 先生,解释得很好,只是为了清楚在上一个示例中您是使用依赖注入完成的,而第一个示例也是松耦合的?
    • 哇,旧答案评论了:)。所以答案是否定的,第一个例子对 CatcherA 有很强的依赖关系,所以它们是强耦合的
    【解决方案7】:

    您可以将(紧密或松散)耦合视为字面意义上的将特定类与其对另一个类的依赖分开所需的工作量。例如,如果你的类中的每个方法在底部都有一个 finally 块,你调用 Log4Net 来记录一些东西,那么你会说你的类与 Log4Net 紧密耦合。如果您的类包含一个名为 LogSomething 的私有方法,这是唯一调用 Log4Net 组件的地方(而其他方法都称为 LogSomething),那么您会说您的类与 Log4Net 松散耦合(因为它不需要太多努力将 Log4Net 拉出来并用其他东西替换它)。

    【讨论】:

    • 那么,“松耦合”实际上意味着更少的依赖?我说的对吗?
    • 它与一个特定类的依赖总数无关。耦合(紧密或松散)实际上是两个类之间关系的属性。因此,您可能有一个类与 100 个其他类松散耦合,或者另一个类仅与其他 2 个类紧密耦合(例如)。
    • 不好的例子,我想说:你所拥有的是代码重复,而不是紧密耦合。并且使用一个好的重构工具,可以在几秒钟内消除这种重复。
    • @Rogerio:这可能不是最好的例子。我自己更喜欢64BitBob 的回答。
    【解决方案8】:

    定义

    本质上,耦合是一个给定对象或一组对象依赖另一个对象或另一组对象以完成其任务的程度。

    高耦合

    想想汽车。为了使发动机启动,必须​​将钥匙插入点火装置,转动,必须存在汽油,必须产生火花,必须点火,并且必须启动发动机。您可以说汽车引擎与其他几个对象高度耦合。这是高耦合,但并不是一件坏事。

    松耦合

    想一想网页的用户控件,它负责允许用户发布、编辑和查看某种类型的信息。单个控件可用于让用户发布一条新信息或编辑一条新信息。该控件应该能够在两个不同的路径之间共享 - 新建和编辑。如果控件的编写方式需要从包含它的页面中获取某种类型的数据,那么您可以说它的耦合度太高。控件应该不需要其容器页面中的任何内容。

    【讨论】:

      【解决方案9】:

      这是一个非常笼统的概念,因此代码示例并不能说明全部情况。

      工作中的一个人对我说,“模式就像分形,当你放大到非常接近时,你可以看到它们,当你缩小到架构级别时,你可以看到它们。”

      阅读简短的维基百科页面可以让您了解这种普遍性:

      http://en.wikipedia.org/wiki/Loose_coupling

      就具体的代码示例而言...

      这是我最近使用的一种松散耦合,来自 Microsoft.Practices.CompositeUI 的东西。

          [ServiceDependency]
          public ICustomizableGridService CustomizableGridService
          {
              protected get { return _customizableGridService; }
              set { _customizableGridService = value; }
          }
      

      此代码声明该类依赖于 CustomizableGridService。它不是直接引用服务的确切实现,而是简单地声明它需要对该服务的一些实现。然后在运行时,系统会解析该依赖关系。

      如果不清楚,您可以在此处阅读更详细的说明:

      http://en.wikipedia.org/wiki/Dependency_injection

      想象一下 ABCCustomizableGridService 是我打算在这里连接的实现。

      如果我选择这样做,我可以将其拉出并用 XYZCustomizableGridService 或 StubCustomizableGridService 替换它,而对具有此依赖关系的类完全不做任何更改。

      如果我直接引用了 ABCCustomizableGridService,那么我需要更改那个/那些引用/s 以便换入另一个服务实现。

      【讨论】:

        【解决方案10】:

        耦合与系统之间的依赖有关,可能是代码模块(函数、文件或类)、管道中的工具、服务器-客户端进程等。依赖关系越不通用,它们就越“紧密耦合”,因为更改一个系统需要更改依赖它的其他系统。理想的情况是“松耦合”,其中一个系统可以更改,而依赖它的系统将继续工作而无需修改。

        实现松散耦合的一般方法是通过定义良好的接口。如果两个系统之间的交互得到了很好的定义并且双方都遵守,那么在确保不违反约定的同时修改一个系统就变得更容易了。在实践中经常出现没有建立良好定义的接口,导致设计草率和紧密耦合。

        一些例子:

        • 应用程序依赖于库。在紧密耦合下,应用程序会在较新版本的库上中断。谷歌的“DLL 地狱”。

        • 客户端应用程序从服务器读取数据。在紧密耦合下,对服务器的更改需要在客户端进行修复。

        • 两个类在面向对象的层次结构中交互。在紧密耦合下,对一个类的更改需要更新另一个类以匹配。

        • 多个命令行工具在管道中通信。如果它们紧密耦合,更改某个命令行工具的版本将导致读取其输出的工具出错。

        【讨论】:

          【解决方案11】:

          耦合是指不同类之间的紧密程度。紧密耦合的类包含大量的交互和依赖关系。

          松散耦合类则相反,因为它们彼此之间的依赖保持在最低限度,而是依赖于彼此定义良好的公共接口。

          乐高积木,SNAP 在一起的玩具会被认为是松散耦合的,因为您可以将这些零件拼在一起并构建您想要的任何系统。然而,一个拼图游戏的部分是紧密耦合的。你不能从一个拼图(系统)中取出一块拼图,然后把它拼到另一个拼图中,因为系统(拼图)非常依赖于为特定“设计”构建的非常具体的拼图。乐高积木以更通用的方式构建,因此可以在您的乐高屋或我的乐高外星人中使用。

          参考:https://megocode3.wordpress.com/2008/02/14/coupling-and-cohesion/

          【讨论】:

            【解决方案12】:

            考虑一个带有 FormA 和 FormB 的 Windows 应用。 FormA 是主窗体,它显示 FormB。想象一下 FormB 需要将数据传回其父级。

            如果你这样做了:

            class FormA 
            {
                FormB fb = new FormB( this );
            
                ...
                fb.Show();
            }
            
            class FormB 
            {
                FormA parent;
            
                public FormB( FormA parent )
                {
                    this.parent = parent;
                }     
            }
            

            FormB 与 FormA 紧密耦合。除了 FormA 类型的父级之外,FormB 不能有其他父级。

            另一方面,如果您让 FormB 发布一个事件并让 FormA 订阅该事件,那么 FormB 可以通过该事件将数据推送回该事件拥有的任何订阅者。那么在这种情况下,FormB 甚至不知道它与父级对话;通过松散耦合,事件提供了它只是与订阅者交谈。任何类型现在都可以成为 FormA 的父级。

            rp

            【讨论】:

              【解决方案13】:

              当两个组件依赖于彼此的具体实现时,它们是高度耦合的。

              假设我在班级的某个方法中的某处有这段代码:

              this.some_object = new SomeObject();
              

              现在我的类依赖于 SomeObject,它们是高度耦合的。另一方面,假设我有一个 InjectSomeObject 方法:

              void InjectSomeObject(ISomeObject so) { // note we require an interface, not concrete implementation
                this.some_object = so;
              }
              

              那么第一个例子可以只使用注入的SomeObject。 这在测试期间很有用。 在正常操作中,您可以使用繁重的、使用数据库的、使用网络的类等,而对于通过轻量级模拟实现的测试。 使用紧密耦合的代码是无法做到这一点的。

              您可以通过使用依赖注入容器来简化这项工作的某些部分。您可以在 Wikipedia 上阅读有关 DI 的更多信息:http://en.wikipedia.org/wiki/Dependency_injection

              有时很容易走得太远。在某些时候,您必须使事情具体化,否则您的程序的可读性和可理解性会降低。所以主要在组件边界使用这种技术,并且知道你在做什么。确保您正在利用松散耦合。如果没有,你可能在那个地方不需要它。 DI 可能会使您的程序更复杂。确保你做出了很好的权衡。换句话说,保持良好的平衡。 一如既往地设计系统。祝你好运!

              【讨论】:

                【解决方案14】:

                在计算机科学中,“松散耦合”还有另一种含义,没有其他人在这里发布过,所以... 来吧 - 希望你能给我一些投票,这样它就不会在底部丢失堆!当然,我回答的主题属于对该问题的任何全面回答......也就是说:

                “松耦合”一词首次进入计算领域时,是作为多 CPU 配置中 CPU 架构的形容词。它的对应术语是“紧耦合”。松耦合是指 CPU 不共享许多公共资源,而紧耦合则是它们共享的资源。

                “系统”一词在这里可能会造成混淆,因此请仔细分析情况。

                通常但并非总是如此,硬件配置中的多个 CPU 存在于一个系统中(如单独的“PC”盒中),它们会紧密耦合。除了一些超高性能系统的子系统实际上在“系统”之间共享主内存之外,所有可分割的系统都是松散耦合的。

                紧耦合和松耦合这两个术语是在多线程和多核 CPU 发明之前引入的,因此这些术语可能需要一些同伴来充分阐明当今的情况。而且,事实上,今天人们很可能拥有一个将两种类型都包含在一个整体系统中的系统。关于当前的软件系统,有两种常见的架构,各有一种,足够常见,应该很熟悉。

                首先,因为这是问题所在,一些松耦合系统的例子:

                • VaxClusters
                • Linux 集群

                相比之下,一些紧耦合的例子:

                • Semetrical-Multi-Processing (SMP) 操作系统 - 例如Fedora 9
                • 多线程 CPU
                • 多核 CPU

                在当今的计算中,两者都在单个整体系统中运行的例子并不少见。例如,以运行 Fedora 9 的现代奔腾双核或四核 CPU 为例——这些是紧密耦合的计算系统。然后,将其中的几个组合到一个松散耦合的 Linux 集群中,您现在可以同时进行松散耦合和紧耦合计算!哦,现代硬件是不是很棒!

                【讨论】:

                  【解决方案15】:

                  在简单的语言中,松散耦合意味着它不依赖于其他事件的发生。它独立执行。

                  【讨论】:

                  • 这不是真的——正如在其他示例中提到的那样,与其说是实体(模块、类)之间是否存在关系,不如说它们是否可以轻松换出其他实现相同功能的类。例如,一个 ViewModel 可能适用于不同的模型,但如果没有一个,它肯定不会工作
                  • 嗯,不是很有帮助
                  【解决方案16】:

                  这里有一些长答案。不过原理很简单。我从wikipedia提交开幕词:

                  “松散耦合描述了两个或多个具有某种交换关系的系统或组织之间的弹性关系。

                  事务的每一端都明确提出其要求,并且对另一端几乎没有假设。”

                  【讨论】:

                  • 如果这么简单,我们就不会有这个讨论了。
                  【解决方案17】:

                  我提出一个非常简单的代码耦合测试

                  1. 如果对代码段 B 进行任何可能的修改,从而强制代码段 A 进行更改以保持正确性,则代码段 A 与代码段 B 紧密耦合。

                  2. 如果没有可能对代码段 B 进行任何修改而需要对代码段 A 进行更改,则代码段 A 与代码段 B 没有紧密耦合。

                  这将帮助您验证代码片段之间的耦合程度。 有关推理,请参阅此博客文章:http://marekdec.wordpress.com/2012/11/14/loose-coupling-tight-coupling-decoupling-what-is-that-all-about/

                  【讨论】:

                    【解决方案18】:

                    当您在其他类中使用 new 关键字创建类的对象时,您实际上是在进行紧密耦合(不好的做法),而应该使用松散耦合,这是一个好的做法

                    ---A.java---

                    package interface_package.loose_coupling;
                    
                    public class A {
                    
                    void display(InterfaceClass obji)
                    {
                        obji.display();
                        System.out.println(obji.getVar());
                    }
                    }
                    

                    ---B.java---

                    package interface_package.loose_coupling;
                    
                    public class B implements InterfaceClass{
                    
                    private String var="variable Interface";
                    
                    public String getVar() {
                        return var;
                    }
                    
                    public void setVar(String var) {
                        this.var = var;
                    }
                    
                    @Override
                    public void display() {
                        // TODO Auto-generated method stub
                        System.out.println("Display Method Called");
                    }
                    }
                    

                    ---接口类---

                    package interface_package.loose_coupling;
                    
                    public interface InterfaceClass {
                    
                    void display();
                    String getVar();
                    }
                    

                    ---主类---

                    package interface_package.loose_coupling;
                    
                    public class MainClass {
                    
                    public static void main(String[] args) {
                        // TODO Auto-generated method stub
                    
                        A obja=new A();
                        B objb=new B();
                        obja.display(objb);     //Calling display of A class with object of B class 
                    
                    }
                    }
                    

                    解释:

                    在上面的例子中,我们有两个类 A 和 B

                    B 类实现接口,即 InterfaceClass。

                    InterfaceClass 为 B 类定义了一个 Contract,因为 InterfaceClass 具有 B 类的抽象方法,可以被任何其他类(例如 A)访问。

                    在 A 类中,我们有显示方法,它可以排除实现 InterfaceClass 的类的对象(在我们的例子中是 B 类)。并且在 A 类的那个对象方法上调用 B 类的 display() 和 getVar()

                    在 MainClass 中,我们创建了 A 类和 B 类的对象。并通过传递 B 类的对象即 objb 来调用 A 的显示方法。 A 的显示方法会被 B 类的对象调用。

                    现在谈论松散耦合。假设将来您必须将B类的名称更改为ABC,那么您不必在B类的显示方法中更改其名称,只需创建新的对象(ABC类)并将其传递给MailClass中的显示方法。您不必更改 A 类中的任何内容

                    参考:http://p3lang.com/2013/06/loose-coupling-example-using-interface/

                    【讨论】:

                      【解决方案19】:

                      您可以阅读有关"loose coupling" 的通用概念的更多信息。

                      简而言之,它是对两个类之间关系的描述,其中每个类对另一个类的了解最少,并且无论另一个类是否存在并且不依赖于特定实现,每个类都可能继续正常工作其他类的。

                      【讨论】:

                        【解决方案20】:

                        一般来说,松散耦合是指 2 个参与者在相同的工作负载上彼此独立工作。因此,如果您有 2 个 Web 服务器使用相同的后端数据库,那么您会说这些 Web 服务器是松散耦合的。紧密耦合可以通过在一台 Web 服务器上拥有 2 个处理器来举例说明......这些处理器是紧密耦合的。

                        希望对您有所帮助。

                        【讨论】:

                        • 我明白你想要什么,但仍然不是一个很好的方式来解释紧密耦合是两个“事物”相互依赖时,而松散耦合是两个“事物”存在时独立 - 一个“东西”可以在不改变另一个“东西”的情况下改变......
                        • 史蒂夫,你完全正确——你不应该得到任何反对票。只是您的观众还没有为您的术语做好准备,而且该网站上的太多人习惯于对他们不理解或不熟悉的内容进行投票。 -耸耸肩-
                        • 我认为史蒂夫没有抓住重点。松散耦合并不总是意味着 2 个参与者在同一工作负载上独立工作。
                        猜你喜欢
                        • 2012-02-18
                        • 1970-01-01
                        • 2013-03-17
                        • 1970-01-01
                        • 2017-06-05
                        • 2013-12-25
                        • 2020-10-26
                        • 2011-02-22
                        • 1970-01-01
                        相关资源
                        最近更新 更多