java - 如何使用控制反转在java中创建即插即用代码?

标签 java design-patterns dependency-injection inversion-of-control software-design

我想为我的团队创建一个 Java SDK,让他们能够创建一个简单的 Java 类(某种插件),将其注册到某个地方,并让 Java 在运行时选择要使用哪个 Java 类插件.

让我们举一个简单的例子:我有 3 个 Java 类。每个内部都有一个函数,它接受一个字符串并分别打印出“Short Greeting”+ inputStr、“Long Greeting”+ inputStr 和“Blah”+ inputStr)。假设它们都实现了一个接口(interface)。

我想要一个设计,这些类将在某个地方注册,明天其他人可以编写第四个类,它会打印出其他内容(也实现相同的接口(interface))。选择哪个类的决定应该基于用户的输入?

即。我可以说 java -jar my.jar -inputString "John"-pluginName="long"

并且 jar 将实例化正确的类并实现正确的逻辑。

我知道我可以有一个简单的 switch case 语句或 if else if 和 else 逻辑,但这是一个微不足道的案例,实际上我希望我的代码模块化,以便将来添加的插件彼此完全独立。

我被告知要研究 IOC 和依赖注入(inject),但我在网上没有找到任何好的教程。任何帮助将不胜感激,提前致谢

<小时/>

是的,也许一个简单的例子不合适。我正在设计一个SDK,用于确定要调用哪个数据存储。我有其他开发人员设计适配器来调用 a(n):

CouchBase(CouchBaseReterival.java)

REST 服务(ServiceRetreival.java)

HBASE 实例(HBASERetreival.java)

所有这些适配器都实现一个接口(interface) (InformationRetreival.java),该接口(interface)具有 getInformation() 方法。

此 SDK 将由微服务中的 REST 调用本身调用。因此,客户端调用将包含参数 x、y、z 和 couchBase 的“cb”。微服务将调用 informationRetrieval.getInformation(x,y,z,"cb")。代码应该注入(inject)正确的适配器并执行逻辑以返回正确的响应。

Switch-Case/if-else 逻辑并没有那么复杂(也许我不应该使用这个词),因为当有多个适配器被独立开发和测试时,它不是一个好的设计模式。 (一个要求是代码的松耦合)我不想每次添加新适配器时都修改代码的逻辑。反射是一种选择,但同样需要更改代码。我正在寻找更多关于利用 Spring 或 PicoContainer 的依赖注入(inject)建议/教程的建议。

最佳答案

在您的具体示例中,对于初学者来说,您会更倾向于“开放/封闭原则”:

interface Greeter {
   public String getGreetingFor(String name);
}

abstract class BaseGreeter implements Greeter {
   public final String getGreetingFor(String name) {
     return getPrefix() + " : " + name;
   }
   protected abstract String getPrefix();
}

class ShortGreeter extends BaseGreeter {
   @Override
   public String getPrefix() { return "Short greeting"; }

这里的想法是:您希望每个Greeter实现都有自己的实现。相反,您放入另一个可以更改的抽象(您可以添加其他问候语),但对修改关闭(问候函数本身不能再被子类覆盖)。

[显然:如果您的接口(interface)的所有实现都确实不同,那么此模式不起作用 - 但至少在您的示例中并非如此]

对于第二部分 - 默认方法是使用 reflection :因为这允许您在运行时仅在字符串上实例化任意类;像:

String pluginClassNameFromUser = "whatever.package.SomeClass";
Class<Greeter> someClassInstance = (Greeter) Class.forName(pluginClassNameFromUser);

但是:听起来 ifs/switches 对你来说已经感觉“复杂”了;所以这对我来说意味着,反射(reflection)远远超出了你目前的技能。

所以,更简单的选择实际上是这样的:

public Greeter fetchGreeterFromUserInput(String userInput) {
  switch userInput.trim().toLowerCase(): {
    case "short": return new ShortGreeter();
    case "long" : ...

我希望这能给您一些如何处理您的项目的灵感。

最后:如果您正在寻找一个广泛的(尽管是高级的示例)来进行“真正的”设计,请查看 Robert Martin 所著的“敏捷实践”(您可以在互联网;即使您不懂 C#,这也是一个很好的起点)。

关于java - 如何使用控制反转在java中创建即插即用代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39198414/

相关文章:

java - 使用 TestNG 进行 Selenium 测试 : The IntelliJ cannot recognize the 'xml' File

java - Checkstyle 规则以避免 not 条件

java - 幸存者空间已满可以触发完整GC吗?

templates - 设计动态模板

dependency-injection - "Inversion of Control"、 "Dependency inversion"和 "Decoupling"之间的区别

javascript - 带有 typescript 接口(interface)的 Aurelia DI

java - 无法从客户端应用程序调用 GWT-RPC

C# - UDPClient 和 Socket 之间的关系

java - @PostConstruct 的执行顺序

java - 带有抽象说明的工厂模式