Strategy Pattern with Spring Boot

3

I've been looking for strategy pattern solutions with spring boot, but nothing I've found so far seems performative or even functional.

I have an interface like:

public interface UserService {
    User getById(Integer id);
}

And I have two different implementations:

@Primary
@Service("userService")
public class UserServiceImpl implements UserService{

    @Override
    public User getById(Integer id){
    //todo here
    }
}

@Service("userRemoteService")
public class UserRemoteServiceImpl implements UserService{

    @Override
    public User getById(Integer id){
    //todo here
    }
}

In the controller I call the interface:

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    //some methods here

}

As it is only the UserServiceImpl will be instantiated and called because it is the primary.

The application can have two states, one in which it queries the local bank and another where it requests a microservice. I need to change the implementation of the UserService that will be consumed by the controller.

I found some solutions, most are versions of if else. I need to find some solution that when I do a refresh scope of the state and it changes, without checking every request I have the correct implementation of the UserService in the controller.

    
asked by anonymous 23.05.2018 / 19:09

1 answer

2

Here's an alternative. Hope it helps!

Interface:

public interface UserService {
  User getById(Integer id);
}

Implementations:

@Bean(name = "userLocalService")
public class UserServiceImpl implements UserService{

  @Override
  public User getById(Integer id){
    //todo here
  }
}

@Bean(name = "userRemoteService")
public class UserRemoteServiceImpl implements UserService{

  @Override
  public User getById(Integer id){
    //todo here
  }
}

Interface factory:

public interface UserServiceFactory {
  UserService getUserService(String userServiceType);
}

Configuration class:

@Configuration()
public class UserServiceConfig {

  @Bean
  public UserService userServiceImpl() {
    return new UserServiceImpl();
  }

  @Bean
  public UserService UserRemoteServiceImpl() {
    return new UserRemoteServiceImpl();
  }

  @Bean
  public ServiceLocatorFactoryBean serviceLocatorFactoryBean() {
    ServiceLocatorFactoryBean serviceLocatorFactoryBean = new ServiceLocatorFactoryBean();
    serviceLocatorFactoryBean.setServiceLocatorInterface(UserServiceFactory.class);
    return serviceLocatorFactoryBean;
  }

  @Bean
  public ConditionUserService() {
      return new ConditionUserService();
  }
}

Service that will define which implementation to use:

@Service
public class ConditionUserService() {

  private String userServiceType = "userLocalService";

  @Autowired
  private UserServiceFactory userServiceFactory;

  public UserService getUserService() {
    return userServiceFactory.getUserService(userServiceType);
  }

  public setUserServiceType(String userServiceType) {
    this.userServiceType = userServiceType;
  }

}

Controller:

@Controller
public class UserController {

  @Autowired
  private ConditionUserService conditionUserService;

  public User getById(Integer id) {
        UserService userService = conditionUserService.getUserService();
        return userService.getById(id);
    }

}

At the moment you want to change the behavior you will call:

conditionUserService.setUserServiceType("userRemoteService");
    
26.05.2018 / 16:57