Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何处理依赖注入策略_Java_Dependency Injection_Guice_Strategy Pattern - Fatal编程技术网

Java 如何处理依赖注入策略

Java 如何处理依赖注入策略,java,dependency-injection,guice,strategy-pattern,Java,Dependency Injection,Guice,Strategy Pattern,我必须创建一个具有本地和外部存储的订单系统。本地存储应始终首先用完,如果仍然缺少任何内容,其余内容应由外部存储订购 基本上我有4种可能的情况: 1从本地存储订购所有项目 从本地存储和外部存储混合的2个订单项目 3从外部存储器订购所有项目 4.无法订购 现在,我决定为3种有效情况创建一个接口。该接口非常简单: public interface Reservator{ boolean reserveItem(Article article, amount); } 现在,我使用以下界面选择哪种策

我必须创建一个具有本地和外部存储的订单系统。本地存储应始终首先用完,如果仍然缺少任何内容,其余内容应由外部存储订购

基本上我有4种可能的情况:

1从本地存储订购所有项目
从本地存储和外部存储混合的2个订单项目
3从外部存储器订购所有项目
4.无法订购

现在,我决定为3种有效情况创建一个接口。该接口非常简单:

public interface Reservator{
  boolean reserveItem(Article article, amount);
}
现在,我使用以下界面选择哪种策略:

public interface ReservationContext{
  boolean setAmount(int amount);
  boolean reserveItem(Article article);
}
其实现大致如下所示:

@Singleton
public ReservationHandler implements ReservationContext{
  private int reservationAmount=0;
  private Reservator reservator;
  private LocalStorage local;
  private ExternalStorage external;

  @Inject
  public ReservationHandler(LocalStorage local, ExternalStorage external){
    this.local = local;
    this.external = external;

  }
  @Override
  public boolean setAmount(int amount){
    if(amount == 0){
      return false;
    }
    if(local.getStorage > amount){
      reservator = new LocalReservator(//all dependencies);
    }
    else if(local.getStorage ==0 && external.getStorage > amount){
      reservator = new ExternalReservator(//all dependencies);
    }
    else if((local.getStorage + external.getStorage) > amount){
      reservator = new MixedReservator(//all dependencies);
    }
    else{
      return false;
    }
    reservationAmount = amount;
    return true;
  }

  @Override
  public boolean reserveItem(Article article){
    return reservator.reserveItem(article, amount);
  }

}
现在我想知道如何通过依赖注入而不是实例来处理三种保留策略(LocalReservator、ExternalReservator和MixedReservator),以便更容易地进行测试

我知道我可以绑定ReservatorInterace的所有实现,并在注入时获得一个列表。然而,我并不完全清楚我如何能轻易地选择正确的一个。在我的案例中,什么是最佳实践


此外,如果正确策略的选择能够得到更好的处理,我愿意接受建议。谢谢你的时间

您的ReservationHandler目前负责至少三件事:创建Reservator实例、计算要使用的Reservator以及充当ReservationContext。虽然这个代码并不是太坏,但我们可以很容易地让Guice处理创建保留实例——毕竟,它的工作是封装依赖性创建——并考虑提取出正确的保留器的创建。如果Reservators的数量增加,或者如果ReservationContext的作用域变得更清晰,那么这也将隔离您。(现在它看起来就像一个包装器接口。)

您需要的不是列表,而是一组提供者:

private final Provider<LocalReservator> localReservatorProvider;
private final Provider<ExternalReservator> externalReservatorProvider;
private final Provider<MixedReservator> mixedReservatorProvider;
你应该这样做吗?现在,您还没有向我们展示您的Reservator实例的依赖关系,或者它们是否可能更改。如果没有,或者列表很短,您可能会坚持使用
new
;如果列表很长或者可能会更改,那么注入提供者是非常有意义的。如果您的实例很难在测试中使用,那么注入提供程序也是有意义的,因为您可以使用一个mock来用一个简单的确定性测试双精度替换一个真正的LocalReservator(其余的以此类推)

如果您想在此基础上进行构建,还可以涉及(这允许您以分布式方式在Guice中创建一个集合或映射,一次一个绑定)或(这将允许您在创建Reservator期间传递构造函数参数,使用您定义的工厂而不是Guice的提供程序)。两者都不适用,但都值得学习

从这里开始,如果您的
setAmount
逻辑足够复杂,无法提取,您还可以将其提取到一个方法类ReservatorFactory,该类选择返回哪个Reservator。这样,您的ReservationHandler就可以由它自己负责,并且可以在不使用特定保留逻辑的情况下进行测试。(当然,如果这是您希望ReservationHandler做的唯一事情,那么请务必将该实现留在原处。否则,您可以将ReservationHandler重构为一个空壳!)


p、 s.Jack的评论是正确的,他说,在为个人预订保留状态的同时,将此标记为
@Singleton
,可能非常危险。您可以删除
@Singleton
注释,Guice每次都会创建一个新实例;这是Guice的默认行为。

您的ReservationHandler当前负责至少三件事:创建Reservator实例、计算要使用的Reservator以及充当ReservationContext。虽然这个代码并不是太坏,但我们可以很容易地让Guice处理创建保留实例——毕竟,它的工作是封装依赖性创建——并考虑提取出正确的保留器的创建。如果Reservators的数量增加,或者如果ReservationContext的作用域变得更清晰,那么这也将隔离您。(现在它看起来就像一个包装器接口。)

您需要的不是列表,而是一组提供者:

private final Provider<LocalReservator> localReservatorProvider;
private final Provider<ExternalReservator> externalReservatorProvider;
private final Provider<MixedReservator> mixedReservatorProvider;
你应该这样做吗?现在,您还没有向我们展示您的Reservator实例的依赖关系,或者它们是否可能更改。如果没有,或者列表很短,您可能会坚持使用
new
;如果列表很长或者可能会更改,那么注入提供者是非常有意义的。如果您的实例很难在测试中使用,那么注入提供程序也是有意义的,因为您可以使用一个mock来用一个简单的确定性测试双精度替换一个真正的LocalReservator(其余的以此类推)

如果您想在此基础上进行构建,还可以涉及(这允许您以分布式方式在Guice中创建一个集合或映射,一次一个绑定)或(这将允许您在创建Reservator期间传递构造函数参数,使用您定义的工厂而不是Guice的提供程序)。两者都不适用,但都值得学习

从这里开始,如果您的
setAmount
逻辑足够复杂,无法提取,您还可以将其提取到一个方法类ReservatorFactory,该类选择返回哪个Reservator。这样,您的ReservationHandler就可以由它自己负责,并且可以在不使用特定保留逻辑的情况下进行测试。(当然,如果这是您希望ReservationHandler做的唯一事情,那么请务必将该实现留在原处。否则,您可以将ReservationHandler重构为一个空壳!)

p、 s.Jack的评论是正确的,他说,在为个人预订保留状态的同时,将此标记为
@Singleton
,可能非常危险。你可以