2015-06-10 65 views
2

我有一個API,它有一些基本實現。我有一家工廠向客戶提供該API的實例。不依賴於實現的工廠

我想改變我的工廠,使其更通用,因此,如果將生成api的新實現並將其jar文件放入classpath中,工廠將理解它,並且不需要任何更改。

+2

看起來像'Reflection'工作。 – CKing

回答

4

使用java SPI,服務提供者接口。

  • API罐 - 提供一個單一接口。
  • 提供程序jar - 在jar中提供實現。你甚至可以把幾個實現放在一個jar中。在一個文本文件META-INF/services/my.package.MyInterface中列出了一個實現類(es)。
  • 應用程序 - 在應用程序中,執行jar不應該用於編譯: 在maven作用域運行時。

服務發現發生了ServiceLoader<T>

public static void main(String[] args) { 
    ServiceLoader<MyInterface> loader = ServiceLoader.load(MyInterface.class); 
    for (MyInterface api : loader) { 
     api. ... 
    } 
    // Or take the first implementation: 
    MyInterface api = loader.iterator().next(); 
} 

你可以提供的API罐子一類與該發現機制的靜態函數。

優點:

  • 分離
  • 可能一些實現
  • 執行的選擇可被動態地完成

罐子

  • XXX-api.jar中
    • 我/包/ MyInterface.class
  • XXX先impl.jar中
    • META-INF /服務/ my.package.MyInterface
      • my.package.impl.MyImpl1
    • 我/包/ IMPL/MyImpl1.class
      • public class MyImpl1 implements MyInterface { ... }
  • myapp1.jar
+1

很好的答案。 https://docs.oracle.com/javase/tutorial/ext/basics/spi.html – kervin

+0

我們在哪裏放置實現類的列表? –

0

如果你想從理論開始。請閱讀約Dependency inversion principle

在面向對象編程中,依賴性反轉原理是指特定形式的解耦軟件模塊。當遵循這一原則時,從高級別策略設置模塊到低級別依賴模塊建立的常規依賴關係被反轉(即反轉),從而使得高級別模塊獨立於低級別模塊實現細節。

答:高級模塊不應該依賴於低級模塊。兩者都應該依賴於抽象。

B.抽象不應該取決於細節。細節應該取決於抽象。

該原理顛倒了一些人可能會考慮面向對象設計的方式,即規定高級和低級對象都必須依賴於相同的抽象。

依賴注入圖書館

至於具體實現,你有很多在Java中。具體爲Dependency Injection方法。顯然想到了Spring Framework。但是你也可以看看Java EE Context and Dependency Injection

接口注入

您還可以...

  1. 裝入罐手動:How should I load Jars dynamically at runtime?
  2. 使用接口注入Spring interface injection example(這個標題所說春天,但答案顯示接口注入不需要彈簧)
+0

@kevin我對這個概念非常熟悉,但是在您提供的示例中,客戶端在編譯時綁定了impl,但在我的情況下,客戶端和工廠直到運行時才知道impl。 這是一些像slf4j方法與其impls。 –

+0

@ Ali.Valizadeh在這兩種情況下,客戶和實施都不需要知道對方。正如維基百科鏈接所解釋的,他們需要一個共享的接口或基類。例如。 「IJob」或「JobBase」類。但是這可能是非常通用的。 – kervin

+0

但有些東西應該爲客戶端提供該接口的實例(在這種情況下是工廠)是否錯誤? –