2016-03-11 3 views
2

Это упрощенная версия того, чего я пытаюсь достичь. У меня есть несколько реализаций одного и того же интерфейса. Основываясь на пользовательском входе во время выполнения, я хочу выбрать правильную реализацию.Решения переключателя пружин, основанные на рабочем состоянии

Например, предположим, что интерфейс называется Color. Существует много классов, реализующих этот интерфейс, класс Red, класс Blue, класс Green и т. Д.

Во время выполнения мне нужно выбрать реализации на основе пользовательского ввода. Одним из способов достижения этой цели было бы что-то вроде этого

@Autowired 
@Qualifier("Red") 
private Color redColor; 

@Autowired 
@Qualifier("Green") 
private Color greenColor; 


private Color getColorImplementation() 
{ 
if(userInput=="red") 
{ 
return redColor; 

} 
else if(userInput=="green") 
{ 
return greenColor; 
} 
else 
{ 
return null; 
} 

} 

Но проблема состоит в том, что каждый раз, когда добавляется новая реализация, я бы обновить код, который выбирает реализацию, который бьет целую цель обращения контрольной части пружины. Каков правильный способ сделать это с помощью весны?

ответ

4

Вы можете автоувеличивать все реализации рассматриваемого интерфейса, а затем решать на основе свойств, предоставляемых интерфейсом, который следует использовать.

@Autowired 
private List<Color> colors; 

public void doSomething(String input) { 
    colors.stream().filter(c -> c.getName().contains(input)).findFirst().ifPresent(c -> { 
     // something 
    } 
} 

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

+1

Очень хорошее решение. Вы можете даже улучшить его, если вы будете объявлять 'Map colors' вместо' List'. Затем новый цвет должен быть объявлен с помощью '@Component (" colorName ")'. В этом случае вы даже можете сделать несколько имен синонимов для одного цвета, и не нужно, чтобы класс 'Color' ничего не знал о разрешении цвета. –

+0

@Ken: Я думаю, что ваш комментарий должен быть частью ответа. Я в конечном итоге использовал карту так, как вы предлагали, а затем извлекал элементы с карты по имени, объявленному в @Component («BeanName»). Отлично! – developer747

+0

@ developer747 Я был рад помочь. Основная идея - список атрибутов bean в зависимости от базового типа, предложенный zapl. Другое это просто детали. –

2

Вы хотите Autowire ApplicationContext, тогда вы можете получить все бобы Color с Map<String, Color> colors = appContext.getBeansOfType(Color.class);. Это предполагает, что userInput и имя компонента идентичны.

Если это не так, то решением было бы добавить getName() в интерфейс Color; то вы можете автоопределить List<Color> и самостоятельно построить карту.

Вы не можете сделать цвет Enum?

+0

Это приемлемая практика? Вызов appContext для получения боба? Но это звучит неплохо. Я могу пойти с этим. – developer747

+0

AppContext уже существует и является autowireable, поэтому никаких дополнительных усилий не требуется. Имейте в виду, вам нужно сделать это только во время конструктора вашего компонента или в '@ PostConstruct'. –

1

Весна ServiceLocatorFactoryBean (прокрутите вниз до середины) API был построен именно для этой цели:

  1. Создать фиктивный интерфейс (ColorFactory), который обеспечивает единый метод такой, как Color getColor(String color)
  2. Создание прокси-боб экземпляр для org.springframework.beans.factory.config.ServiceLocatorFactoryBean, проходящий ColorFactory как параметр serviceLocatorInterface
  3. Определить beans для всех ваших реализаций цвета с именами, соответствующими параметру, который вы хотите передать, getColor
  4. Инжектируйте завод в коллаборационист и вызывать getColor при необходимости

Вы можете затевать это с подобным API, на ApplicationContext, но преимущество такого подхода заключается в том, что она абстрагируется Spring от вашей реализации Java (для XML сконфигурированного проекты).

+0

Вот пример http: //www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring – user3198603

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