什么是“松耦合”?请提供例子


172

我似乎无法理解“松散耦合”的概念。我想这不利于单词“宽松”通常有负面的含义,所以我总是忘了松耦合是一个很好的事情。

有人可以显示说明此概念的“之前”和“之后”代码(或伪代码)吗?


我不确定如何将其与特定语言相分离,因为该概念的一部分是人们如何使用一种语言来防止代码单元彼此纠缠在一起。我还注意到,有几个答案是通过代码来说明这一概念的。
Onorio Catenacci

11
完全不同意,实用性在不同的语言中可以用不同的方式说明,在动态语言和编译语言中尤为明显。但是,无论哪种方式,概念都是相同的。
Owen,

松与紧,联与脱。标记总是不是一件好事,有时是好/有时是不好的。。。因为我们应该有自己的独立性,所以课堂也应如此。
bonCodigo 2014年

Answers:


180

考虑一个简单的购物车应用程序,该应用程序使用CartContents类来跟踪购物车中的项目,并使用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类)如何取决于CartContents和CartEntry类的实现细节。如果我们试图更改此逻辑以允许折扣,则可能必须更改所有三个类别。另外,如果我们更改为使用List集合来跟踪商品,则也必须更改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);
    }
}

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


您能否扩展答案,通过依赖注入进一步引入解耦(尽管构造函数应该是理想的)?
BAD_SEED 2013年

4
@Wedge,我认为没有理由对Order有所了解Cart。现场购物和制造是两种不同的情况。当客户准备付款时,您可以有一个流程负责将CartEntries转换成对有意义的东西Order。这样一来,Order该类也将被实例化,并且无需使用Cart
plalx

@楔您能对我的评论做出反应吗?
plalx

好吧,简单地解释一下。我开始看到“ ..注意OrderTotal方法(以及Order类)如何取决于CartContents和CartEntry类的实现细节。”
okey_on 2015年

这个例子很清楚。但是,如今,越来越多的建筑师同意这种过度的面向对象风格是一种不好的做法。有一个在隐藏的“执行”的细节没有意义CartEntryCartContents。由于这些具有完全清晰的含义,因此应将它们简单地建模为无效数据。用数据库的术语来说,这里只需要一个表CREATE TABLE entry (price INTEGER, quantity INTEGER)
Jo So

160

iPodiPad等许多集成产品(尤其是Apple的产品)就是紧密耦合的一个很好的例子:一旦电池耗尽,您最好购买新设备,因为电池已焊接固定并且不会松动,因此更换非常容易昂贵。松散耦合的播放器可以轻松更换电池。

这同样也适用于软件开发:它通常是(多)最好有松耦合代码,方便扩展和替换(并且使各个部件更容易理解)。但是,在极少数情况下,紧密耦合可能是有利的,因为几个模块的紧密集成可以实现更好的优化。


松动或紧密耦合好吗?如何决定实现松耦合还是紧耦合?
Sreekanth Karumanaghat

2
谢谢这个伟大的例子。我花了很多时间在其他答案上,但是却不值得这样
alamin 2015年

1
Sreekanth Karumanaghat,您是愿意只花很少的钱来购买电池并再次使用iPod,还是想花很多钱购买整个iPod?
Koshera '16

1
@SreekanthKarumanaghat通常,松耦合会更好,因为它可以促进模块化,从而使代码更易于维护。如果您将类/库/代码紧密地结合在一起,那么您在一个类中所做的任何细微更改都必须在使用它的所有类中实现。
肯尼·沃登

55

我将以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。或者换句话说,它们是与父类“分离”或“松散耦合”的。

但是,如果我们需要两者之间的沟通怎么办?好了,然后我们可以使用事件模型等其他抽象来确保父代码永远不需要与您创建的API耦合。


2
这个例子仍然有很高的耦合度。到目前为止,有两种可供选择,而不是只与一个类耦合。本示例假定只有两个“ Runnable”实现可用。在这种情况下,甚至不需要接口。
Owen,

这些Run *和Do *命名的方法对我来说是一种巨大的代码味道。您最好将其重构为使用IHandleStuff或IFrobnicateThings。在这种情况下,Runnable实在太笼统了。
楔子

8
欧文,宝贝,踩我的朋友。如果他不了解耦合,他将如何理解工厂模式会给他带来什么?此代码示例使他处于正确的轨道。目的是让他更好地理解问题并意识到如何抽象出对象的创建。
2008年

6
如果将ABC和XYZ重命名为诸如DiskAccessor和,这是否更易读NetworkAccessor?我不知道没有Java ...
MusiGenesis'Oct

是否也使用工厂设计模式?因为我们根据需要创建新的XYZ或ABC对象。
munmunbb

37

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

松散耦合只是意味着应该构造各个设计元素,从而减少了他们需要了解的有关其他设计元素的不必要信息。

高内聚性有点像“紧密耦合”,但高内聚性是一种状态,在这种状态下,真正需要彼此了解的设计元素经过精心设计,可以干净,优雅地协同工作。

关键是,某些设计元素应了解其他设计元素的详细信息,因此应以这种方式进行设计,而不是偶然地进行设计。其他设计元素不应该知道其他设计元素的详细信息,因此应该有目的地而不是随机地进行设计。

留给读者练习是实现:)。


33

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

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

然后我依赖于ArrayList实现。

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

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

这样可以防止我调用任何方法myList特定于ArrayList实现的。我仅限于List接口中定义的那些方法。如果以后再决定确实需要一个LinkedList,则只需要在创建新List的一个地方更改代码,而不是在对ArrayList方法进行调用的100个地方更改代码。

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


这几乎涉及到什么是“耦合”,实际上。有关一些好的答案,请参见stackoverflow.com/questions/39946/coupling-and-cohesion
罗杰里奥(Rogério)2010年

@Rogerio:我认为这是相关的。也许您对“耦合”的其他定义感到困惑,但是您应该阅读松散耦合。“当从属类包含直接指向提供所需行为的具体类的指针时,就会发生强耦合。当从属类仅包含指向接口的指针时,就会发生松散耦合,然后可以由一个或多个具体类来实现”。在我的示例中,我的代码将通过List接口与ArrayList松散耦合。
Bill Lizard

@Bill:感谢您的链接,但是那篇文章对我来说似乎完全是伪造的。似乎是在“重新解释”来自另一个领域(组织行为)的观点,给出了“松散耦合”的定义,该定义与Larry Constantine最初的软件特定定义相矛盾:en.wikipedia.org/wiki/Coupling_(computer_science)
罗杰里奥(Rogério)2010年

@Rogerio:君士坦丁的论文写于1974年。在过去的36年中,很可能进行了许多重新解释,但我认为Wikipedia的文章并不源于此。例如,像依赖注入这样的模式依赖于接口来松开耦合,正如我在回答中所描述的那样。
比尔蜥蜴

2
@Bill:当然,君士坦丁在结构化设计方面的工作是陈旧的,但是我看不出有任何理由使它无效或从根本上重新解释它。凝聚和耦合的原始概念与继承和多态性一样,都是面向对象设计的核心。DI(更好的文章是martinfowler.com/articles/injection.html)仅是一种用于插件的外部配置的技术(抽象的接口以及在运行时通过配置代码选择的实现);另一种这样的技术是服务定位器模式。DI和耦合是独立的概念。
罗杰里奥(Rogério)2010年

26

此处答案之间的差异程度说明了为什么很难理解这个概念,但将其简单地描述为:

为了让我知道,如果我向您扔一个球,那么您就可以接住球,我真的不需要知道您多大了。我不需要知道您早餐吃了什么,而且我真的不在乎您的第一个恋人是谁。我所需要知道的是,您可以抓住。如果我知道这一点,那么我不在乎它是否是我向您或您的兄弟扔球。

对于非动态语言,例如c#或Java等,我们可以通过Interfaces来实现。所以可以说我们有以下界面:

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");
   }

}

现在,CatcherA和CatcherB都实现了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服务未与CatcherA或CatcherB紧密耦合。

还有一些其他策略可用于松散地耦合服务,例如使用IoC框架等。


1
我比其他例子更喜欢这个例子,因为这种事情在商业世界中每天都会发生。如果运行Class Person,运行Cat类,运行Dog狗等,则将是一个庞大的程序,用于详细说明所有运行的类。但是,使用一个名为runs的接口(每个类都执行相同的操作),可以使程序更加灵活和易于管理。:)
sksallaj

先生,解释得非常好,只是为了在上一个示例中清楚您使用依赖项注入来做到这一点,而第一个示例也是松散耦合的?
阿里·萨吉德

哇,旧答案评论了:)。因此,答案是否定的,第一个例子对CatcherA hard依赖关系,使他们强耦合
欧文

23

您可以认为(紧密或松散)耦合实际上是您将特定类从对另一个类的依赖中分离出来所需要付出的努力。例如,如果类中的每个方法在底部调用Log4Net记录某些内容的底部都有一个finally块,那么您会说您的类与Log4Net紧密耦合。如果您的类包含一个名为LogSomething的私有方法,而该方法是唯一一个调用Log4Net组件的地方(其他方法都称为LogSomething),那么您会说您的类与Log4Net松散耦合了(因为它不需要太多时间)努力拉出Log4Net并将其替换为其他东西)。


1
那么,“松散耦合”实际上意味着更少的依赖关系?我对么?
user314362'9

4
它实际上与一个特定类所具有的依赖关系总数无关。耦合(紧密或松散)实际上是两个类之间关系的属性。因此,您可能有一个类别与100个其他类别松散耦合,或者另一个类别与2个其他类别紧密耦合(例如)。
MusiGenesis

2
我会说一个不好的例子:您拥有的是代码重复,而不是紧密耦合。有了良好的重构工具,这种重复可以在几秒钟内消除。
罗杰里奥(Rogério)2010年

@Rogerio:这可能不是最好的例子。我64BitBob自己更喜欢答案。
MusiGenesis

12

定义

从本质上讲,耦合是给定对象或一组对象完成另一个任务所依赖的对象。

高耦合

想想一辆车。为了使发动机启动,必须​​将钥匙插入点火开关中,转动,必须存在汽油,必须产生火花,必须点火活塞,并且发动机必须带电。您可以说汽车发动机与其他几个物体高度耦合。这是高耦合,但这并不是一件坏事。

松耦合

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


7

这是一个非常笼统的概念,因此代码示例不会给出完整的图片。

在这里工作的一个人对我说:“图案就像分形,当您放大得很近时,以及缩小到建筑级别时,您都可以看到它们。”

阅读简短的维基百科页面可以使您大致了解一下:

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,则需要对该引用进行更改,以便交换另一个服务实现。


6

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

实现松散耦合的一般方法是通过定义明确的接口。如果两个系统之间的交互作用得到很好的定义,并且双方都坚持,那么在确保不破坏约定的同时修改一个系统变得更加容易。在实践中通常会发生以下情况:没有建立明确定义的接口,从而导致设计草率和紧密耦合。

一些例子:

  • 应用程序取决于库。在紧密耦合下,应用程序在较新版本的lib上中断。Google的“ DLL Hell”。

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

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

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


5

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

松散耦合的类是相反的,因为它们彼此之间的依赖关系被最小化,而是相互依赖定义良好的公共接口。

乐高玩具,即SNAP在一起的玩具,可以认为是松散耦合的,因为您可以将零件拼合在一起,并构建所需的任何系统。但是,拼图游戏的零件紧密相连。您不能从一个拼图游戏(系统)中提取一个片段并将其捕捉到另一个拼图中,因为系统(拼图)非常依赖于针对特定“设计”而构建的非常具体的片段。乐高积木以更通用的方式构建,因此可以在您的Lego House或我的Lego Alien Man中使用。

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


4

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

假设我的代码在类的某个方法中的某处:

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可能会使您的程序更复杂。确保您进行了良好的权衡。换句话说,保持良好的平衡。与设计系统时一样。祝好运!


3

考虑带有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紧密耦合。FormB只能有FormA类型的父对象。

另一方面,如果您让FormB发布事件并让FormA订阅该事件,则FormB可以将数据通过该事件推回该事件拥有的任何订户。然后,在这种情况下,FormB甚至不知道其与父级的对话。通过松散耦合,事件提供了与订阅者的简单对话。现在,任何类型都可以成为FormA的父级。

rp


3

在计算机科学中,“松散耦合”还有另一种含义,这是其他人都没有发表的意思,所以……来吧-希望您能给我一些票,以免这没错。当然,我的回答的主题属于对该问题的任何全面回答。

术语“松散耦合”首先进入计算领域,该术语用作有关多CPU配置中CPU体系结构的形容词。它的对应术语是“紧密耦合”。松散耦合是指CPU不共享许多资源,而紧密耦合是指CPU共享时。

“系统”一词在这里可能令人困惑,因此请仔细分析情况。

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

在发明多线程和多核CPU 之前,先引入了紧密耦合和松散耦合这两个术语,因此这些术语可能需要一些同伴来全面阐述当今的情况。而且,的确,今天,很可能拥有一种在一个整体系统中同时包含两种类型的系统。对于当前的软件系统,有两种通用的体系结构,每种体系中的一种,它们足够通用,应该很熟悉。

首先,既然是问题所在,那么松耦合系统的一些示例:

  • Vax集群
  • Linux集群

相反,一些紧密耦合的示例:

  • 对称多处理(SMP)操作系统-例如Fedora 9
  • 多线程CPU
  • 多核CPU

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


3

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


1
并非真的如此-就像在其他示例中提到的那样,与实体(模块,类)之间是否存在关系并没有太大关系,而是可以轻松地将它们换成实现相同功能的其他类。例如,一个ViewModel可能适用于不同的模型,但是如果没有一个模型,它肯定无法工作
Hayden Crocker

嗯,不是很有帮助
brgs

2

这里有一些长答案。原理很简单。我提交了维基百科的开幕词:

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

事务的每一端都明确规定了其要求,而对另一端几乎没有任何假设。”


1
如果它是如此简单,我们将不会进行讨论。
brgs

2

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

  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/


2

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

--- 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类的显示方法中更改其名称,只需创建new对象(ABC类)并将其传递给MailClass中的显示方法即可。您无需在A类中进行任何更改

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


0

您可以阅读有关“松耦合”的一般概念的更多信息。

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


-8

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

希望这会有所帮助。


1
我明白了您要做什么,但仍然不能很好地解释紧密耦合是两个“事物”相互依赖时的情况,而松散耦合是两个“事物”独立存在时的情况-其中一个“事物”可以可以更改而无需更改其他“东西” ...
布赖恩·里贝因

史蒂夫,您说得很对-您不应该得到任何不赞成票。只是您的听众还没有为您的术语做好准备,并且该站点上的太多人习惯于否决他们不了解或不熟悉的内容。
理查德·T

我认为史蒂夫没有讲到重点。松散耦合并不总是意味着2个参与者在相同的工作负载下独立工作。
罗布
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.