如何用枚举中每种环境类型的值列表表示键? [英] How can I represent key with list of values for each environment type in an Enum?

查看:53
本文介绍了如何用枚举中每种环境类型的值列表表示键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个环境PRODSTAGING.在生产环境中,我们有三个数据中心ABCDEFPQR,而暂存有一个数据中心CORP.每个数据中心只有几台机器,我为它们定义了常量,如下所示:

I have two environment PROD and STAGING. In prod environment we have three datacenters ABC, DEF and PQR and staging has one datacenter CORP. Each datacenter has few machines and I have constant defined for them as shown below:

// NOTE: I can have more machines in each dc in future
public static final ImmutableList<String> ABC_SERVERS = ImmutableList.of("tcp://machineA:8081", "tcp://machineA:8082");
public static final ImmutableList<String> DEF_SERVERS = ImmutableList.of("tcp://machineB:8081", "tcp://machineB:8082");
public static final ImmutableList<String> PQR_SERVERS = ImmutableList.of("tcp://machineC:8081", "tcp://machineC:8082");

public static final ImmutableList<String> STAGING_SERVERS = ImmutableList.of("tcp://machineJ:8087","tcp://machineJ:8088");

现在,我在同一类中定义了另一个常量,该常量将DC划分为每种环境类型的计算机列表.

Now I have another constant defined in the same class which groups by DC to List of machines for each environment type.

public static final ImmutableMap<Datacenter, ImmutableList<String>> PROD_SERVERS_BY_DC =
  ImmutableMap.<Datacenter, ImmutableList<String>>builder()
      .put(Datacenter.ABC, ABC_SERVERS).put(Datacenter.DEF, DEF_SERVERS)
      .put(Datacenter.PQR, PQR_SERVERS).build();

public static final ImmutableMap<Datacenter, ImmutableList<String>> STAGING_SERVERS_BY_DC =
  ImmutableMap.<Datacenter, ImmutableList<String>>builder()
      .put(Datacenter.CORP, STAGING_SERVERS).build();

现在在其他班上,根据我在(Utils.isProd())中所处的环境,我会得到PROD_SERVERS_BY_DCSTAGING_SERVERS_BY_DC.

Now in some other class, basis on what environment I am in (Utils.isProd()), I get either PROD_SERVERS_BY_DC or STAGING_SERVERS_BY_DC.

Map<Datacenter, ImmutableList<String>> machinesByDC = Utils.isProd() ? Utils.PROD_SERVERS_BY_DC : Utils.STAGING_SERVERS_BY_DC;

现在,我认为可以用某种枚举以更好的方式表示它,而不是像上面定义的那样定义常量,但是我不知道该怎么办?我从这开始,但是对于如何为每个DC拥有一个键,然后为该DC的机器列表拥有多个值感到困惑,然后我还需要按环境对它们进行分组.

Now I think this can be represented in much better way in some sort of Enum instead of having constants defined like I have above but I am not able to figure out how can I do that? I started off with this but got confuse on how can I have single key for each DC and then multiple values as List of machines for that DC and then I need to group them by environment as well.

// got confuse on how can I make key (DC) and list of values (machines) for each environment type.
public enum DCToMachines {
  abc(tcp://machineA:8081", "tcp://machineA:8082"), 

  private final List<String> machines;
  private final Datacenter datacenter;
  ...


}

推荐答案

我从此开始,但对如何拥有一把钥匙感到困惑 每个DC,然后有多个值作为该DC的计算机列表 然后我还需要根据环境对它们进行分组.

I started off with this but got confuse on how can I have single key for each DC and then multiple values as List of machines for that DC and then I need to group them by environment as well.

您忘记了一个重要的建议:枚举可能存储特定于每个枚举值的成员(方法和字段),但如果需要,它也可能存储static成员.
您需要直接在enum类中移动按环境分组的地图:

You forgot an important just : enum may store members (method and fields) specific to each enum value but it may also store static members if required.
What you need is moving the maps that groups by environment directly in the enum class :

private static final ImmutableMap<Datacenter, ImmutableList<String>> PROD_SERVERS_BY_DC;
private static final ImmutableMap<Datacenter, ImmutableList<String>> STAGING_SERVERS_BY_DC;

您可以根据用户请求使用内部地图返回期望的地图:

You could use an inner map to return the expected map according to the user request :

private static final Map<Env, ImmutableMap<Datacenter, ImmutableList<String>>> SERVERS_BY_ENV;

Env是另一个枚举的地方:

Where Env is another enum :

public static enum Env {
    PROD, STAGING
}

在我将要提供的代码中,我将其添加为Datacenter的封闭类型,但在其自己的文件中可能会更好,因为环境可能不是数据中心专门使用的概念.

In the code that I will present I added as an enclosing type of Datacenter but it would be probably better in its own file as the environment is probably not a concept used exclusively by datacenters.

最后,您使用的按环境检索服务器的方式将相关职责划分为两个类(Datacenter枚举和当前类):

At last, the way you are using to retrieve servers by environment splits related responsibilities in 2 classes (Datacenter enum and the current class) :

Map<Datacenter, ImmutableList<String>> machinesByDC = Utils.isProd() ? Utils.PROD_SERVERS_BY_DC : Utils.STAGING_SERVERS_BY_DC;

在枚举中引入执行此操作的方法会更好:

introducing in the enum a method to do this operation would be nicer :

public static ImmutableMap<Datacenter, ImmutableList<String>> getServers(Env env){...}

这将增加枚举类的凝聚力.

Which would increase the cohesion of the enum class.

以下是更新的枚举:

import java.util.HashMap;
import java.util.Map;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;

public enum Datacenter {

   ABC(Env.PROD, "tcp://machineA:8081", "tcp://machineA:8082"), 
   DEF(Env.PROD, "tcp://machineB:8081", "tcp://machineB:8082"), 
   PQR(Env.PROD, "tcp://machineA:8081", "tcp://machineA:8082"), 
   CORP(Env.STAGING, "tcp://machineC:8081", "tcp://machineC:8082");

    public static enum Env {
        PROD, STAGING
    }

    private Env env;
    private String[] url;

    private static final ImmutableMap<Datacenter, ImmutableList<String>> PROD_SERVERS_BY_DC;
    private static final ImmutableMap<Datacenter, ImmutableList<String>> STAGING_SERVERS_BY_DC;
    private static final Map<Env, ImmutableMap<Datacenter, ImmutableList<String>>> SERVERS_BY_ENV;

    static {

        Builder<Datacenter, ImmutableList<String>> prodDataCenterBuilder = ImmutableMap.<Datacenter, ImmutableList<String>>builder();
        Builder<Datacenter, ImmutableList<String>> stagingDataCenterBuilder = ImmutableMap.<Datacenter, ImmutableList<String>>builder();

        for (Datacenter datacenter : Datacenter.values()) {
            if (datacenter.env == Env.PROD) {
                prodDataCenterBuilder.put(datacenter, ImmutableList.of(datacenter.url));
            } else if (datacenter.env == Env.STAGING) {
                stagingDataCenterBuilder.put(datacenter, ImmutableList.of(datacenter.url));
            }

            else {
                throw new IllegalArgumentException("not exepected env " + datacenter.env);
            }
        }

        PROD_SERVERS_BY_DC = prodDataCenterBuilder.build();
        STAGING_SERVERS_BY_DC = stagingDataCenterBuilder.build();

        SERVERS_BY_ENV = new HashMap<>();
        SERVERS_BY_ENV.put(Env.PROD, PROD_SERVERS_BY_DC);
        SERVERS_BY_ENV.put(Env.STAGING, STAGING_SERVERS_BY_DC);

    }

    Datacenter(Env env, String... url) {
        this.env = env;
        this.url = url;
    }    

    public static ImmutableMap<Datacenter, ImmutableList<String>> getServers(Env env) {
        ImmutableMap<Datacenter, ImmutableList<String>> map = SERVERS_BY_ENV.get(env);
        if (map == null) {
            throw new IllegalArgumentException("not exepected env " + env);
        }
        return map;
    }

}

这里是如何使用它:

public static void main(String[] args) {        
    ImmutableMap<Datacenter, ImmutableList<String>> servers = Datacenter.getServers(Env.PROD);
    servers.forEach((k, v) -> System.out.println("prod datacenter=" + k + ", urls=" + v));

    servers = Datacenter.getServers(Env.STAGING);
    servers.forEach((k, v) -> System.out.println("staging datacenter=" + k + ", urls=" + v));
}

输出:

prod datacenter = ABC,urls = [tcp://machineA:8081,tcp://machineA:8082]

prod datacenter=ABC, urls=[tcp://machineA:8081, tcp://machineA:8082]

prod datacenter = DEF,urls = [tcp://machineB:8081,tcp://machineB:8082]

prod datacenter=DEF, urls=[tcp://machineB:8081, tcp://machineB:8082]

prod datacenter = PQR,urls = [tcp://machineA:8081,tcp://machineA:8082]

prod datacenter=PQR, urls=[tcp://machineA:8081, tcp://machineA:8082]

staging datacenter = CORP,urls = [tcp://machineC:8081, tcp://machineC:8082]

staging datacenter=CORP, urls=[tcp://machineC:8081, tcp://machineC:8082]

这篇关于如何用枚举中每种环境类型的值列表表示键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆