我目前正在开展一个涉及创建抽象层的项目。该项目的目标是在我可能需要切换到服务器软件时支持多种服务器软件实现。要抽象的功能列表相当长,所以我想要以一种相当轻松的方式来实现它。
其他应用程序将能够与我的项目进行交互,并进行最终归结为传递到我正在使用的服务器的调用。
这就是问题所在。我在这个领域没有多少经验,我真的不确定如何让它成为死亡的三明治。这是一个大致应该是它的样子链(以及我想要完成的事情)。
/*
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链更好)以及每个抽象级别的课程。
这似乎非常基本但我无法提出解决此问题的逻辑解决方案。如果我没有清楚地解释我的观点,请解释我需要详细说明的内容。也许我在想这件事情是错的?
答案 0 :(得分:2)
为什么不使用控制反转?
您拥有自己的抽象集,创建了多个实现,然后配置公共API以使用其中一个实现。
您的API受实现继承的接口集保护。您可以在以后添加新实现而无需修改API代码,甚至可以在运行时进行切换。
我不知道如果控制反转是依赖注入,或者DI是Ioc的一种形式,那么......它只是你从组件中删除了依赖管理的责任。 / p>
在这里,你将有
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入口点上进行操作(从最近的入口点注入)。
所以客户端加载他想要的jar,使用他想要的工厂或注入impl的配置,并使用你的代码。这还取决于你如何暴露你的api。