2016-07-22 144 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友好的面孔之間的一些合作,我能夠把它放在一起。 –