根据您所在的环境传递必需的参数来实例化类

时间:2017-10-26 21:19:52

标签: java oop design-patterns enums

我有一个以下枚举类,其中包含少量字段stagePoolSizeprodPoolSizeenabled

  public enum Type {
    process_caty(5, 8, false), process_misc1(5, 8, false), link_entry(5, 12, true);
    private final int stagePoolSize;
    private final int prodPoolSize;
    private final boolean enabled;

    private Type(int stagePoolSize, int prodPoolSize, boolean enabled) {
      this.stagePoolSize = stagePoolSize;
      this.prodPoolSize = prodPoolSize;
      this.enabled = enabled;
    }

    public int getStagePoolSize() {
      return stagePoolSize;
    }

    public int getProdPoolSize() {
      return prodPoolSize;
    }

    public boolean isEnabled() {
      return enabled;
    }

    @Override
    public String toString() {
      return name() + "=" + stagePoolSize + "=" + prodPoolSize + "=" + enabled;
    }
  }

这就是我使用上面的枚举来初始化我的Handler类。

  private final List<Handler> handlers = new ArrayList<>();

  @PostConstruct
  public void postInit() {
    String datacenter = Utils.getDatacenter();

    for (Type consType : Type.values()) {
      if (!consType.isEnabled()) {
        continue;
      }
      int poolSize = Utils.isProd() ? consType.getProdPoolSize() : consType.getStagePoolSize();
      handlers.add(new Handler(consType, poolSize));
    }
  }

如果启用了任何枚举,那么根据我们所处的环境(无论是Prod还是Stage),通过此调用Utils.isProd()进行检查,我们得到它poolSize然后使用poolSize 1}}初始化Handler类。

问题陈述:

现在我需要在同一个Type类中添加更多枚举,但我需要为它们做些不同的事情。以下是我需要添加的枚举:

abc_raw_pho
abc_raw_slq
abc_raw_lvk
abc_raw_pin_pho
abc_raw_pin_slq
abc_raw_pin_lvk

以下是我们需要为以上新枚举做的事情:

  • 仅在环境为Prod时使用。他们将有一些prodPool大小的值。
  • 如果我们在pho datanceter中,那么我们应该使用以pho结尾的枚举。如果我们在slq数据中心,那么我们应该使用以slq结尾的枚举。同样适用于lvk。

我可以通过调用此方法找出我们所在的数据中心:

    String datacenter = Utils.getDatacenter();

现在我应该如何设计我的Type枚举类,以便我的原始枚举可以正常工作,并且我的新数据中心枚举最终适用于上述条件。以下是整体要求:

  • process_caty应该同时用于StageProd,并且应该根据它所处的环境相应地使用poolSize。
  • process_misc1应该同时用于StageProd,并且应该根据它所处的环境相应地使用poolSize。
  • link_entry应该同时用于StageProd,并且应该根据它所处的环境相应地使用poolSize。
  • abc_raw_pho仅适用于Prod,但取决于我们所在的数据中心,它应仅使用poolSize for Prod。
  • abc_raw_slq仅适用于Prod,但取决于我们所在的数据中心,它应仅使用poolSize for Prod。
  • abc_raw_lvk仅适用于Prod,但取决于我们所在的数据中心,它应仅使用poolSize for Prod。
  • abc_raw_pin_pho仅适用于Prod,但取决于我们所在的数据中心,它应仅使用poolSize for Prod。
  • abc_raw_pin_slq仅适用于Prod,但取决于我们所在的数据中心,它应仅使用poolSize for Prod。
  • abc_raw_pin_lvk仅适用于Prod,但取决于我们所在的数据中心,它应仅使用poolSize for Prod。

1 个答案:

答案 0 :(得分:1)

我会重构你的枚举并将其分解为更小的类,为EnvironmentDataCenterPoolSizes引入模型:

public enum Environment {PROD, STAGE}

public enum DataCenter {PHO, SLQ, LVK, NA /*Not applicable*/}

public class PoolSizes {

    public static final int SIZE_UNDEFINED = -1;

    private Map<Environment, Integer> environmentValues;

    public PoolSizes() {
        environmentValues = new HashMap<>();
    }

    public PoolSizes withStagePoolSize(int size) {
        environmentValues.put(Environment.STAGE, size);
        return this;
    }   

    public PoolSizes withProductionPoolSize(int size) {
        environmentValues.put(Environment.PROD, size);
        return this;
    }

    public int getPoolSize(Environment environment) {
        Integer size = environmentValues.get(environment);
        return size != null ? size : SIZE_UNDEFINED;            
    }        
}

然后Type枚举将使用这些来简化池化查找的逻辑并确定是否启用了类型:

public enum Type {

    PROCESS_CATY(new PoolSizes().withStagePoolSize(5).withProductionPoolSize(8), 
        DataCenter.NA, false), 
    PROCESS_MISC1(new PoolSizes().withStagePoolSize(5).withProductionPoolSize(8), 
        DataCenter.NA, false), 
    LINK_ENTRY(new PoolSizes().withStagePoolSize(5).withProductionPoolSize(12), 
        DataCenter.NA, true),

    ABC_RAW_PHO(new PoolSizes().withProductionPoolSize(123), DataCenter.PHO, true),
    ABC_RAW_SLQ(new PoolSizes().withProductionPoolSize(123), DataCenter.SLQ, true),
    ABC_RAW_LVK(new PoolSizes().withProductionPoolSize(123), DataCenter.LVK, true),

    ABC_RAW_PIN_PHO(new PoolSizes().withProductionPoolSize(123), DataCenter.PHO, true),
    ABC_RAW_PIN_SLQ(new PoolSizes().withProductionPoolSize(123), DataCenter.SLQ, true),
    ABC_RAW_PIN_LVK(new PoolSizes().withProductionPoolSize(123), DataCenter.LVK, true);

    private final PoolSizes poolSizes;
    private final DataCenter dataCenter;
    private final boolean enabled;

    private Type(PoolSizes poolSizes, DataCenter dataCenter, boolean enabled) {
      this.poolSizes = poolSizes;
      this.dataCenter = dataCenter;
      this.enabled = enabled;
    }

    public int getPoolSize(Environment environment) {
      return poolSizes.getPoolSize(environment);
    }

    public DataCenter getDataCenter() {
        return this.dataCenter;
    }

    public boolean isEnabled(Environment environment, DataCenter dataCenter) {
      return enabled && poolSizes.getPoolSize(environment) != PoolSizes.SIZE_UNDEFINED 
              && (getDataCenter() == DataCenter.NA || getDataCenter() == dataCenter);
    }
  }

最后,postInit()方法会变成这样:

public void postInit() {
    DataCenter dataCenter = Utils.getDataCenter();
    Environment environment = Utils.getEnvironment();

    for (Type consType : Type.values()) {
      if (!consType.isEnabled(dataCenter, environment)) {
        continue;
      }
      handlers.add(new Handler(consType, consType.getPoolSize(environment)));
    }
}