当前位置: 首页 > 面试题库 >

在接口级别将两个类解耦是什么意思?

梁丘扬
2023-03-14
问题内容

假设我们在A包中有A类,在B包中有B类。如果类A的对象引用了类B,则称这两个类在它们之间具有耦合。

为了解决这种耦合,建议在包A中定义一个接口,该接口由包B中的类实现。然后,类A的对象可以引用包A中的接口。这通常是“依赖倒置”的一个例子。

这是“在接口级别将两个类解耦”的示例。如果是,当两个类耦合时,它如何消除类之间的耦合并保持相同的功能?


问题答案:

让我们创建一个虚拟的例子。

A套餐类别packageA

package packageA;

import packageB.B;

public class A {
    private B myB;

    public A() {
        this.myB = new B();
    }

    public void doSomethingThatUsesB() {
        System.out.println("Doing things with myB");
        this.myB.doSomething();
    }
}

B套餐类别packageB

package packageB;

public class B {
    public void doSomething() {
        System.out.println("B did something.");
    }
}

如我们所见,A取决于B。没有BA则不能使用。但是,如果B将来我们想用a
代替BetterB呢?对于这一点,我们创建了一个界面InterpackageA

package packageA;

public interface Inter {
    public void doSomething();
}

为了利用这个界面,我们

  • import packageA.Inter;B implements InterB
  • 用替换所有B内部的A出现Inter

结果是该版本的修改版A

package packageA;

public class A {
    private Inter myInter;

    public A() {
        this.myInter = ???; // What to do here?
    }

    public void doSomethingThatUsesInter() {
        System.out.println("Doing things with myInter");
        this.myInter.doSomething();
    }
}

我们已经看到,从A到的依赖关系B消失了:import packageB.B;不再需要。仅存在一个问题:我们无法实例化接口的实例。但是控制反转才是真正的解决方案:与其InterA构造函数中实例化某种类型的东西,构造器将需要一些implements Inter作为参数的东西:

package packageA;

public class A {
    private Inter myInter;

    public A(Inter myInter) {
        this.myInter = myInter;
    }

    public void doSomethingThatUsesInter() {
        System.out.println("Doing things with myInter");
        this.myInter.doSomething();
    }
}

通过这种方法,我们可以改变现在的具体实施InterA随意。假设我们编写了一个新类BetterB

package packageB;

import packageA.Inter;

public class BetterB implements Inter {
    @Override
    public void doSomething() {
        System.out.println("BetterB did something.");
    }
}

现在我们可以A使用不同的Inter实现实例化:

Inter b = new B();
A aWithB = new A(b);
aWithB.doSomethingThatUsesInter();

Inter betterB = new BetterB();
A aWithBetterB = new A(betterB);
aWithBetterB.doSomethingThatUsesInter();

而且我们不必更改其中的任何内容A。现在,代码已解耦Inter,只要满足了合同,我们就可以随意更改的具体实现Inter。最值得一提的是,我们可以支持将在以后编写并实现的代码Inter

附录

我两年多以前写了这个答案。在总体上对答案感到满意的同时,我始终以为缺少了一些东西,我想我终于知道了那是什么。以下内容对于理解答案不是必需的,而是旨在引起读者的兴趣,并为进一步的自我教育提供一些资源。

在文献中,这种方法被称为接口隔离原理,属于
SOLID
原理

。YouTube上Bob叔叔有一个很好的演讲(有趣的一点是大约15分钟长),展示了如何使用多态和接口使编译时依赖点指向控制流(建议观看者酌情决定,Bob叔叔将关于Java的轻描淡写。相应地,这意味着当高层实现通过接口隔离时,不需要高层实现。因此,如上所述,可以随意交换较低的级别。



 类似资料:
  • 假设A包中有A类,B包中有B类。如果类A的对象引用了类B,那么这两个类之间就称为耦合。 为了解决耦合问题,建议在包A中定义一个接口,该接口由包B中的类实现。然后,类A的对象可以引用包A中的接口。这通常是《依赖倒置》中的一个例子。 这是不是“在接口层解耦两个类”的例子,如果是,它是如何去除类之间的耦合,并在两个类耦合时保留相同的功能的?

  • 问题内容: 假设我们在A包中有A类,在B包中有B类。如果类A的对象引用了类B,则称这两个类之间具有耦合。 为了解决耦合问题,建议在包A中定义一个接口,该接口由包B中的类实现。然后,类A的对象可以引用包A中的接口。这通常是“依赖倒置”的一个例子。 这是“在接口级别将两个类解耦”的示例。如果是,当两个类耦合时,它如何消除类之间的耦合并保持相同的功能? 问题答案: 让我们创建一个虚拟的例子。 套餐类别:

  • 在mongodb文档中,它说: 从版本2.2开始,MongoDB在每个数据库的基础上为大多数读写操作实现锁。一些全局操作(通常是涉及多个数据库的短期操作)仍然需要全局“实例”范围的锁。在2.2之前,每个mongod实例只有一个“全局”锁。 这是否意味着在我有3个连接到网络上运行的不同应用程序的mongodb://localhost/test的情况下——一次只能写一个?还是只是每个连接? IOW:它

  • 这点我见过提过几次,但我不清楚是甚么意思。你什么时候为什么要这么做? 我知道接口是做什么的,但我不清楚这一点的事实使我认为我错过了正确使用它们。 如果你要做: 您可以使用任何实现的类?你什么时候需要这么做?我唯一能想到的是,如果您有一个方法,但您不确定会传递什么对象,除了它实现。我想不出你需要多长时间这样做一次。 另外,如何编写一个方法来接受一个实现接口的对象呢?有可能吗?

  • 我在理解语句。我已经在谷歌上搜索并阅读了很多关于这方面的内容,但仍然觉得很难理解。 据我所知,高内聚意味着我们应该有专门的类来执行特定的功能。希望这是正确的?就像信用卡验证类一样,它专门用于验证信用卡。 还不明白低耦合是什么意思?

  • 问题内容: 我已经看过几次了,但我不清楚它的含义。您何时以及为什么要这样做? 我知道接口的作用,但是我不清楚这一点,这让我觉得我错过了正确使用它们的机会。 如果要这样做,是否只是这样: 您可以使用任何实现的类吗?您什么时候需要这样做?我唯一能想到的是,如果您有一个方法并且不确定要实现的对象将传递什么对象。我想不出您需要多久这样做一次。 另外,如何编写一个方法来接受实现接口的对象?那可能吗? 问题答