4

我目前正在从事一个涉及创建抽象层的项目。该项目的目标是支持服务器软件的多种实现,以防我可能需要切换到它。要抽象的功能列表相当长,所以我想研究一种相当轻松的方法来做到这一点。

其他应用程序将能够与我的项目进行交互并进行调用,最终归结为传递给我正在使用的服务器。

问题就在这里。我在这方面没有太多经验,我真的不知道如何使它不成为死亡三明治。这是一个大致应该是什么样子的链条(以及我想要完成的事情)。

/*
Software that is dependent on mine
    |
Public API layer (called by other software)
    |
Abstraction between API and my own internal code (this is the issue)
    |
Internal code (this gets replaced per-implementation, as in, each implementation needs its own layer of this, so it's a different package of entirely different classes for each implementation)
    |
The software I'm actually using to write this (which is called by the internal code)
*/

抽象层(显然是最中间的那个)是我努力拼凑的。

现在,我只停留在一个愚蠢的方面。我怎么可能使抽象层不是一系列

public void someMethod() {
    if(Implementation.getCurrentImplementation() == Implementation.TYPE1) {
        // whatever we need to do for this specific implementation
    else {
        throw new NotImplementedException();
    }
}

(原谅伪代码;另外,想象一下相同的情况,但对于一个开关/案例,因为这可能比每个方法的 if 链更好)每个抽象级类中的每个方法。

这似乎非常基本,但我无法想出一个合乎逻辑的解决方案来解决这个问题。如果我没有清楚地解释我的观点,请解释我需要详细说明的内容。也许我在想这整件事是错的?

4

1 回答 1

1

为什么不使用控制反转?

您拥有一组抽象,创建多个实现,然后配置公共 api 以使用其中一个实现。

您的 API 受到实现继承的一组接口的保护。您可以稍后添加新的实现而无需修改 API 代码,甚至可以在运行时切换。


我不再知道控制反转是否是依赖注入,或者 DI 是否是 Ioc 的一种形式,但是......只是您从组件中删除了依赖管理的责任。

在这里,您将拥有

  • API 层(客户端使用的接口)
  • 实现(无限)
  • 包装器(通过引入 impl 来执行 IoC)

API层:

// my-api.jar
public interface MyAPI {
    String doSomething();
}

public interface MyAPIFactory {
    MyAPI getImplementationOfMyAPI();
}

实现:

// red-my-api.jar
public class RedMyAPI implements MyAPI {
    public String doSomething() {
        return "red";
    }
}

// green-my-api.jar
public class GreenMyAPI implements MyAPI {
    public String doSomething() {
        return "green";
    }
}

// black-my-api.jar
public class BlackMyAPI implements MyAPI {
    public String doSomething() {
        return "black";
    }
}

一些包装器提供了一种配置正确实现的方法。在这里,您可以在工厂中隐藏您的开关盒,或从配置中加载 impl。

// wrapper-my-api.jar
public class NotFunnyMyAPIFactory implements MyAPIFactory {
    private Config config;

    public MyAPI getImplementationOfMyAPI() {
        if (config.implType == GREEN) {
            return new GreenMyAPI();
        } else if (config.implType == BLACK) {
            return new BlackMyAPI();                
        } else if (config.implType == RED) {
            return new RedMyAPI();                
        } else { 
           // throw...
        }
    }
}

public class ReflectionMyAPIFactory implements MyAPIFactory {
    private Properties prop;

    public MyAPI getImplementationOfMyAPI() {
        return (MyAPI) Class.forName(prop.get('myApi.implementation.className'))
    }
}

// other possible strategies

工厂允许使用多种策略来加载类。根据解决方案,您只需添加新的依赖项并更改配置(并重新加载应用程序......或不重新加载)即可更改实现。

您可能还想测试性能。

如果使用 Spring,则只能在代码中使用接口,并且从配置类中注入正确的实现(Spring 是一个 DI 容器)。但不需要使用 Spring,您可以直接在 Main 入口点执行此操作(从最近的入口点注入)。

  • my-api.jar 没有依赖项(或者可能对内部层有一些依赖项)。
  • 所有实现的 jar 都依赖于 my-api.jar 和你的内部代码。
  • 包装 jar 依赖于 my-api.jar 和一些 impl jar。

所以客户端加载他想要的jar,使用他想要的工厂或注入impl的配置,然后使用你的代码。这还取决于您如何公开您的 api。

于 2016-07-22T22:23:28.440 回答