首页 > 解决方案 > 为什么我们需要在应用程序开发中使用接口,然后再使用各自的 impl 类而不是直接 impl 类

问题描述

我在许多应用程序中看到,用户定义的接口将被定义,然后它们各自的实现类可用。然后我们将再次从接口级别调用这些实现类方法。

我们我们正在遵循这种方法吗?这背后有什么重要的想法吗?

为什么我们不能在没有接口的情况下直接植入类?

非常感谢您,如果有人清楚地说明这一点。

标签: javajakarta-ee

解决方案


接口在客户端(使用接口的类)和概念的实现细节之间提供了一定程度的间接性。例如,如果我们想创建一个将数据存储在数据库中的持久层,我们可以简单地创建一个对特定类型的数据库(例如A)执行持久性的类。问题是我们系统中使用数据库A的类的其余部分现在与数据库 A 的实现细节相关

如果我们稍后决定使用数据库B ,将A类换成B类可能会很困难。相反,如果我们创建了一个接口,它抽象了两个数据库A和 BRepository共同细节,我们可以为持久化对象提供一个简化的外观。然后我们可以为AB创建一个实现:Repository

public interface Repository {
    public void save(Object object);
    public Object findById(long id);
}

public class ADatabaseRepository implements Repository {

    @Override
    public void save(Object object) {
        // ... save object in database A ...
    }

    @Override
    public Object findById(long id) {
        // ... find object with id in database A ...
    }
}

public class BDatabaseRepository implements Repository {

    @Override
    public void save(Object object) {
        // ... save object in database B ...
    }

    @Override
    public Object findById(long id) {
        // ... find object with id in database B ...
    }
}

然后一些客户端类,Client可以依赖于接口Repository,而不是一些特定的实现类:

public class Client {

    private final Repository repository;

    public Client(Repository repository) {
        this.repository = repository;
    }

    public void doSomething() {
        Object desiredObject = repository.findById(1);
        // ...
    }
}

Repository这允许我们在运行时提供to的任何实现,Client而无需更改任何代码Client

ADatabaseRepository a = new ADatabaseRepository();
BDatabaseRepository b = new BDatabaseRepository();

// Create with A
Client clientA = new Clinet(a);

// Create with B
Client clientB = new Client(b);

警告:虽然接口非常有用,但它们可能会被过度使用。如果存在不需要间接的情况,例如某个接口可能只有一个实现,则可以使用一个类来代替接口和类(尽管这样做的决定是一个判断调用; 没有硬性规定)。使用类会产生不必要的复杂性的接口。

有关接口的常见用例的更多信息,请参阅以下内容:


推荐阅读