2016-07-22 95 views
4

我目前正在研究一个涉及创建抽象层的项目。该项目的目标是支持服务器软件的多种实现,以便我可能需要切换到它。要抽象的特征列表相当长,所以我想要以一种相当无痛的方式来做到这一点。抽象层(Java)

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

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

/* 
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(); 
    } 
} 

(原谅伪码;此外,想象中的一样的情况,但对于一个开关/情况,因为这可能比链更好如果是针对每种方法)针对每个抽象级别类中的每个方法。

这似乎很基本,但我不能想出一个合理的解决方案来解决这个问题。如果我没有清楚解释我的观点,请解释我需要详细阐述的内容。也许我在想这件事是错的?

+0

为什么中等水平是必需的?我看到它的方式,第二层(公共API)是一个接口(或一组接口),第四层(内部代码)表示接口实现或具体类,因实现而异。所有需要的是一次性的配置来选择适当的实现类,其余的可以开箱即用。 – shmosel

+0

@shmosel它可能不是。这代表了一个“层”,因为我不确定这是否是解决我的问题的正确方案。我不太确定我应该在那个“水平”上做什么,如果甚至达到这个水平的话。 –

回答

2

为什么不使用控制反转?

你有你的一套抽象,你创建了几个实现,然后你配置你的公共API来使用其中一个实现。

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


我不知道了,如果控制反转依赖注入,或者如果DI是国际奥委会一种形式。但它只是你删除依赖管理的从组件的责任。

在这里,你将不得不

  • 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。

+0

[控制反转](https://stackoverflow.com/questions/3058/what-is-inversion-of-control)?尽管如此,我对实际做到这一点感到困惑。 –

+0

现在更彻底,谢谢。 :)由于你和IRC友好的面孔之间的一些合作,我能够把它放在一起。 –