2015-06-10 4 views
2

У меня есть api, который имеет некоторые базовые реализации. У меня есть фабрика, которая дает экземпляры этого api для клиентов.Завод, который не зависит от реализации

Я хочу изменить свою фабрику, чтобы сделать ее более общей, поэтому, если будет создана новая реализация api, и ее файл jar будет помещен в classpath, фабрика поймет это, и любые изменения не понадобятся ,

+2

выглядит как работа для 'Reflection'. – CKing

ответ

4

Используйте интерфейс SPI java, интерфейс поставщика услуг.

  • API jar - Обеспечить один интерфейс.
  • Баннер поставщика - Обеспечивает реализацию в банках. Вы можете даже положить несколько реализаций в банку. В текстовом файле META-INF/services/my.package.MyInterface перечислены классы реализации.
  • Приложение - В приложении реализация комбайна не нужна для компиляции: в среде выполнения 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 баночке с статической функцией для этого механизма обнаружения.

Преимущества:

  • Разделение
  • несколько реализаций возможных
  • Выбор реализации может быть сделано динамически

Пример банок

  • ххх-api.jar
    • моего/пакет/MyInterface.class
  • ххх-первых, impl.jar
    • META-INF/услуги/my.package.MyInterface
      • my.package.impl.MyImpl1
    • мой/пакет/осущ/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.

В объектно-ориентированном программировании принцип инверсии зависимостей относится к определенной форме развязывающих программных модулей. Следуя этому принципу, обычные отношения зависимостей, установленные из модулей высокого уровня, устанавливающих политику, на модули низкого уровня, перестраиваются (т. Е. Наоборот), что делает модули высокого уровня независимыми от деталей реализации модуля низкого уровня.

A. Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций.

B. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Принцип инвертирует то, как некоторые люди могут думать об объектно-ориентированном дизайне, диктуя, что объекты с высоким и низким уровнем должны зависеть от той же абстракции.

Dependency Injection Библиотека

Что касается конкретных реализаций, у вас есть много в Java. В частности, для подхода Dependency Injection. Spring Framework, очевидно, приходит на ум. Но вы также можете посмотреть Java EE Context and Dependency Injection.

Injection Интерфейс

Вы также можете ...

  1. Загрузите баночки вручную: How should I load Jars dynamically at runtime?
  2. Использование Интерфейс Injection: Spring interface injection example (Это название говорит весна, но ответы показывают не требуется пружина для инжекции интерфейса)
+0

@kevin Я знаком с концепцией, но в примерах, которые вы указали, клиент связывается во время компиляции с имплантом, но в моем случае клиент и фабрика не знают об импорте до времени выполнения. Это что-то вроде slf4j-подхода с его impls. –

+0

@ Ali.Valizadeh Ни в одном случае клиент или реализация не должны знать друг о друге. Как поясняет ссылка в Википедии, для них потребуется общий интерфейс или базовый класс. Например. «IJob» или «JobBase». Но это может быть очень общим. – kervin

+0

Но что-то должно предоставить экземпляр этого интерфейса для клиента (в данном случае фабрики). Это неправильно? –

Смежные вопросы