2017-07-24 61 views
3

我有一个问题,我试图解决。我需要能够根据用户的输入返回实现。我已经研究过使用抽象工厂模式,但我不确定它是否是最好的方法(或者如果Spring可以帮助我一点)。如何在运行时选择bean实现在春天

这里的工厂将返回接口:

public interface Flow { 
    List<Message> execute(String sessionKey); 
} 

和1实现该接口的:

@Component("AssignSeatFlow") 
public class AssignSeatFlow implements ChatbotFlow { 

    private SeatService seatService; 

    @Autowired 
    public AssignSeatFlow(final SeatService seatService) { 
     this.seatService = seatService; 
    } 

    @Override 
    public List<Message> execute(String sessionKey) { 
     // Implementation here 
    } 
} 

我现在的工厂接口:

public interface FlowFactory { 

    Flow getFlow(final String intentCode); 

} 

及其实现:

@Component 
public class FlowFactoryImpl implements FlowFactory { 

    @Resource("AssignSeatFlow") 
    private Flow assignSeatFlow; 

    @Override 
    public Flow getFlow(final String intentCode) { 
     if(StringUtils.isNullOrEmpty(intentCode)) { 
      throw new IllegalArgumentException("Intent Code cannot be empty"); 
     } 

     switch (intentCode.toUpperCase()) { 
      case "AssignSeatFlow": 
       return assignSeatFlow; 
      default: 
       throw new IllegalArgumentException("Unable to determine flow"); 
     } 
    } 
} 

这个看起来并不理想的原因是,当我添加更多的流程时,工厂将变得更大,每次我都会修改它。我也不是Autowiring字段的粉丝,因为它使测试更加复杂和不太明确。

感谢您的任何反馈意见。

回答

1

我会从那里直接注入Spring上下文到我的工厂并获得豆:

@Autowired 
private ApplicationContext ctx; 
. 
. 
. 
public Flow getFlow(final String intentCode) { 
    return ctx.getBean(intentCode); 
} 

我离开了错误处理,但是这是基本的想法。通过这种方式,您可以添加一个工厂,在添加更多流程类型时,您永远不必触碰它。

访问应用程序上下文不是一个很好的通用实践,因为它鼓励人们使用spring作为服务定位器。但它对工厂来说非常合适。

+0

我听说这不是一个好主意,但它确实使它看起来非常干净(并且可维护!) – StylePotato