use*_*318 5 java spring factory inversion-of-control
在重构一些代码的同时,我发现我们应该在几个地方使用一些多态,而不是必须在这个地方有一堆if/else块.
虽然面向对象的类很容易实现,但是当我们必须决定使用什么实现时,就会出现问题.似乎有很多解决方案,但我想看看是否有更优雅或"最佳实践"的方法来做到这一点.
所以基本上,例如,为了举例说明,我将选择一张信用卡,对于每种信用卡类型,我都有一个实现.因此我有这样的类结构:
每个子类都将扩展CreditCard超类.
现在在Web应用程序中,我将传递一个String,表示用户选择的卡类型.现在我需要将它路由到实际的实现类本身.这是众多选择发挥作用的地方.
如果有更好的选择或者我坚持这些,请告诉我.
工厂:
@Autowired @Qualifier("visa") private CreditCard visa;
@Autowired @Qualifier("mastercard") private CreditCard mastercard;
@Autowired @Qualifier("amex") private CreditCard amex;
public CreditCard getCreditCard(String input) {
{
if ("visa".equals(input)) {
return visa;
} else if ("mastercard".equals(input)) {
return mastercard;
} else if ("amex".equals(input)) {
return amex;
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
地图:
@Autowired HashMap<String, CreditCard> creditCardImpls;
public CreditCard getCreditCard(String input) {
return creditCardImpls.get(input);
}
Run Code Online (Sandbox Code Playgroud)
ApplicationContext getBean:
@Autowired private ApplicationContext applicationContext;
public CreditCard getCreditCard(String input) {
return applicationContext.getBean(input);
}
Run Code Online (Sandbox Code Playgroud)
我在这里看到的问题是,如果我们将来要添加更多信用卡类型,我将不得不在可能的几个不同领域进行自动装配.然后,Map的问题是我们没有使用Spring来抓取bean.对于来自ApplicationContext的getBean,我们不遵循Spring提供的IoC.
这个问题的最佳解决方案或最佳实践是什么?
首先对您的解决方案进行一些评论,然后是我自己的建议。
input)映射,而且每次要引入新的信用卡类型时,都需要修改工厂类代码。CreditCard抽象。与您的评论相反,“它不是使用 Spring 来确定要使用哪个 bean”,该映射以 bean ID 作为键,并且由 Spring 自动装配,因此我们实际上在这里广泛使用 Spring。然而,由于映射键是 bean ID,因此将业务逻辑(信用卡类型 - input)与技术实现(Spring bean ID)混合在一起。如果您想实现一个单独的 bean 来处理“mastercard Platinum”信用卡类型怎么办?由于技术原因,您不能拥有这样的 bean ID(由于空间)。或者在某些时候您会希望某个 Bean 可以处理多种卡片类型。然后,您需要在业务标识符和 bean ID 之间实现另一个转换映射。请参阅下面我的解决方案以进行增强。我的建议是将业务密钥与 bean ID 分开。因此我们需要CreditCard能够说出它可以处理哪种信用卡类型。
abstract class CreditCard {
public abstract String getType();
}
Run Code Online (Sandbox Code Playgroud)
然后每个子类返回自己的类型。
或者
abstract class CreditCard {
private String type;
protected CreditCard(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
Run Code Online (Sandbox Code Playgroud)
每个子类super(<the subclass type>)在自己的构造函数中调用构造函数。
然后,在工厂里,你就可以这样实施。
@Autowire private Collection<CreditCard> creditCards;
private Map<String, CreditCard> creditCardsMap = new HashMap<>();
@PostCostruct
public void mapCreditCards() {
for (CreditCard creditCard : creditCards) {
creditCardsMap.put(creditCard.getType(), creditCard);
}
}
public CreditCard getCreditCard(String type) {
return creditCardsMap.get(type);
}
Run Code Online (Sandbox Code Playgroud)
@PostConstruct方法将在(所有类型为 的 bean)自动装配后运行,creditCards从而CreditCard允许在业务键而不是技术键下进行动态发现和映射。
| 归档时间: |
|
| 查看次数: |
449 次 |
| 最近记录: |