2017-07-24 60 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