Spring Boot Strategy

Hi I have a strategy template in a spring boot application. All my strategies have auto-constructors. I am new to spring boot. I don’t have the simplest idea of ​​how I will write my factory classes for strategies, since auto-generated constructors have introduced dependencies. I appreciate any help I get from this.

NOTE: I leave Integr and base classes outside so as not to clutter up the pattern.

public class StrategyA implement Strategy { private DependencyA depA; private DependencyB depB; @Autowired public StragegyA(DependencyA depA, DependencyB depB) { this.depA = depA; this.depB = depB; } } public class StrategyB implements Strategy { private DependencyA depA; private DependencyB depB; @Autowired public StragegyB(DependencyA depA, DependencyB depB) { this.depA = depA; this.depB = depB; } } public class StrategyFactory { public Strategy getStrategy(String strategyName) { if (name.equals("StrategyA")) { <b>return StrategyA; //My problem is here } else { return StrategyB; // And Here } } } 
+5
source share
4 answers

All previous answers use fairly direct use of spring DI. However, it is also possible to use a ServiceLocatorFactoryBean to create a factory without specifying any bean in the factory. First define the interface for the factory:

 public interface MyFactory { Strategy get(String type); } // Could be an abstract class public interface Strategy { void doStuff(); } 

Then in your application:

 @Configuration public class AppConfiguration { @Autowired private BeanFactory beanFactory; public ServiceLocatorFactoryBean myFactoryLocator() { final ServiceLocatorFactoryBean locator = new ServiceLocatorFactoryBean(); locator.setServiceLocatorInterface(MyFactory.class); locator.setBeanFactory(beanFactory); return locator; } @Bean public MyFactory myFactory() { final ServiceLocatorFactoryBean locator = myFactoryLocator(); locator.afterPropertiesSet(); return (MyFactory) locator.getObject(); } } 

Now you can define a bean (using the @Service, @Component, or @Bean annotation) that implements / extends and automatically registers with MyFactory bean and can be created using

 myFactory.get("beanName"); 

The best part is you can register the bean strategy as lazy and with different areas.

+3
source

Make your StrategyFactory another Spring bean and enter all the strategies in the factory:

 @Component public class StrategyFactory { private final List<Strategy> strategies; @Autowired public StrategyFactory(List<Strategy> strategies) { this.strategies = strategies; } public Strategy getStrategy(String strategyName) { // iterate through the strategies to find the right one, and return it. } } 

I usually use an enumeration rather than a String to identify stratehy, and each Strategy returns the return value of the enumeration, so iteration can be as simple as

 return strategies.stream().filter(strategy -> strategy.getType() == type).findAny().orElseThrow( () -> new IllegalStateException("No strategy found for type " + type)); 

Of course, you can also save strategies on the map inside the constructor to perform an O (1) search.

+5
source

I suggest you make your StrategyFactory a bean and enter Map<String, Strategy> . Spring, enter the bean strategy name as the key, and the value will be the strategy itself. Then all you have to do is call get on this Map .

Here is an example:

 @SpringBootApplication public class So44761709Application { public static void main(String[] args) { SpringApplication.run(So44761709Application.class, args); } public interface Strategy { } @Component public static class DependencyA {} @Component public static class DependencyB {} @Component("StrategyA") public static class StrategyA implements Strategy { private DependencyA depA; private DependencyB depB; @Autowired public StrategyA(DependencyA depA, DependencyB depB) { this.depA = depA; this.depB = depB; } } @Component("StrategyB") public class StrategyB implements Strategy { private DependencyA depA; private DependencyB depB; @Autowired public StrategyB(DependencyA depA, DependencyB depB) { this.depA = depA; this.depB = depB; } } @Component public class StrategyFactory { @Autowired private Map<String, Strategy> strategies; public Strategy getStrategy(String strategyName) { return strategies.get(strategyName); } } @Bean CommandLineRunner run(StrategyFactory strategyFactory) { return args -> { System.out.println(strategyFactory.getStrategy("StrategyB").getClass().getSimpleName()); System.out.println(strategyFactory.getStrategy("StrategyA").getClass().getSimpleName()); }; } } 

Print

 StrategyB StrategyA 
+3
source
 @Component public class StrategyFactory { private StrategyA sA; private StrategyB sB; @Autowired public StrategyFactory (StrategyA sA, StrategyB sB) { this.sA = sA; this.sB = sB; } public Strategy getStrategy(String strategyName) { if (name.equals("StrategyA")) { return sA; //My problem is here } else { return sB; // And Here } } } 

Use the same approach with autowiring all strategies

+2
source

Source: https://habr.com/ru/post/1269226/


All Articles