2013-10-30 90 views
1

我知道这是不可能在Java扩展枚举,但我试图找到下面扩展字段枚举的Java

一个完美的解决方案,我尝试建模枚举(或类)将包含不同地区的各种网络服务的端点,例如我有服务A和B,每个服务在美国,欧盟,JP或CN都有4个区域特定的端点。 (这基本上是我编写的一些独立的调试代码,在生产中将从配置中挑选端点)

我希望能做到这样的事情(不符合标准的java代码)。

public enum IEndPoint { 
    NA_END_POINT, 
    EU_END_POINT, 
    JP_END_POINT, 
    CN_END_POINT, 
} 

public enum ServiceAEndPoint extends IEndPoint { 
    NA_END_POINT("http://A.com/"); 
    EU_END_POINT("http://A-eu.com/"); 
    JP_END_POINT("http://A-jp.com/"); 
    CN_END_POINT("http://A-cn.com/"); 
} 

,我对每个区域的方法,但在我看来枚举方法更清晰,有没有更好的办法,我可以模拟这个我能做到这一点使用接口?我正在寻找的是如果有更好的方法来建模遗传关系,并且具有枚举的表达能力。

ServiceAEndPoint.NA_END_POINT 

VS

serviceAEndPoint.getNAEndPoint() 
+0

你不能把一个构造函数和一个getter放在你的IEndPoint枚举中吗? – Julien

回答

1

如果这些都是静态的最后常数,则只是把它们的接口。将接口命名为IServiceAEndPointKeys,其中部分是一种约定。

这里就是我认为枚举 s到更合适的和有用的:

  • 例1:文件类型。一个枚举包含jpg,pdf
  • 示例2:列定义。如果我有3列的表,我会写一个枚举声明ID名称说明(例如),每一个具有像列标题名称列宽列ID参数
3

我假设你也想要一个ServiceBEndPoint枚举(和类似的)。在这种情况下,我认为你的模型确实没有多大意义。

IEndPoint实际上是一种服务可能运行的环境/区域的枚举。这不是服务本身的列举。每个单独的服务(A,B或其他)对于每个区域将具有不同的地址。

因此,我会坚持只是IEndPoint枚举,然后在一些特定于服务的代码中有一个查找映射,它将为您提供给定端点的地址。事情是这样的:

public enum IEndPoint { 
    NA_END_POINT, 
    EU_END_POINT, 
    JP_END_POINT, 
    CN_END_POINT, 
} 

public class ServiceABroker { 
    private static final Map<IEndPoint, String> addressesByEndPoint; 
    static { 
     addressesByEndPoint = new EnumMap<>(); 
     addressesByEndPoint.put(NA_END_POINT, "http://A.com/"); 
     addressesByEndPoint.put(EU_END_POINT, "http://A-eu.com/"); 
     addressesByEndPoint.put(JP_END_POINT, "http://A-jp.com/"); 
     addressesByEndPoint.put(CN_END_POINT, "http://A-cn.com/"); 
    } 

    public String getAddressForEndPoint(IEndPoint ep) { 
     return addressesByEndPoint.get(ep); 
    } 
} 
+0

我喜欢这个服务层方法比我提出的解决方案更好。 –

+0

感谢您的回复,但这仍然不能解决最初的问题,即不必将终点表示为字符串,因此我为什么认为有一个类或其周围的枚举会使其更具表现力。 –

+0

@jack_carver - 无论如何,你可以用“url”属性(除其他外)将它表示为一个对象。但是对象本身(特定于区域的服务实例)与端点不同,它只是四个值中的一个。它们不是一回事,只是它们之间存在关系。这对我来说最有意义的是在终点和serviceA-that-is-running-there之间有这张地图。 –

1

你可能要考虑这样的事情:

public abstract class EndpointFactory { 
    public abstract String getNAEndPoint(); 
    public abstract String getEUEndPoint(); 
} 

public class ServiceAEndpointFactory extends EndpointFactory { 
    public static final String NA_END_POINT = "http://A.com/"; 
    public static final String EU_END_POINT = "http://A-eu.com/"; 

    public String getNAEndPoint() { 
     return ServiceAEndpointFactory.NA_END_POINT; 
    } 

    public String getEUEndPoint() { 
     return ServiceAEndpointFactory.EU_END_POINT; 
    } 
} 

public class ServiceBEndpointFactory extends EndpointFactory { 
    public static final String NA_END_POINT = "http://B.com/"; 
    public static final String EU_END_POINT = "http://B-eu.com/"; 

    public String getNAEndPoint() { 
     return ServiceAEndpointFactory.NA_END_POINT; 
    } 

    public String getEUEndPoint() { 
     return ServiceAEndpointFactory.EU_END_POINT; 
    } 
} 

然后,你可以参考你的字符串直接像这样:

ServiceAEndpointFactory.NA_END_POINT; 

或者,你可以使用基础对象如果服务类型直到执行时才知道:

EndpointFactory ef1 = new ServiceAEndpointFactory(); 
String ep = ef1.getNAEndPoint(); 

其缺点是重新定义每个子类中的get * Endpoint()函数。通过将静态最终变量移动到基类中不是静态的,并将getter/setter只放入基类中一次,可以消除这种情况。然而,这样做的缺点是你不能在没有实例化对象的情况下引用这些值(这基本上模仿了我在ENUM中发现的有价值的东西)。

1

林不知道我理解你的问题,但你可以添加方法来枚举例如,你可以这样做以下:

public enum ServiceAEndPoint{ 
    NA_END_POINT("http://A.com/"); 
    EU_END_POINT("http://A-eu.com/"); 
    JP_END_POINT("http://A-jp.com/"); 
    CN_END_POINT("http://A-cn.com/"); 

    private final String url; 

    private EndPoint(String url){ 
     this.url=url; 
    } 

    public String getURL(){ 
     return url; 
    } 
} 
1

枚举不能以这样的方式进行扩展,主要是因为枚举不能被分类或必须遵守的约束条件是不可能实施的。

相反杠杆接口,像这样

public interface IEndPoint; 

public enum DefaultEndPoints implements IEndPoint { 
    NA_END_POINT, 
    EU_END_POINT, 
    JP_END_POINT, 
    CN_END_POINT, 
} 

public enum DefaultServiceEndPoints implements IEndPoint { 
    NA_END_POINT("http://A.com/"); 
    EU_END_POINT("http://A-eu.com/"); 
    JP_END_POINT("http://A-jp.com/"); 
    CN_END_POINT("http://A-cn.com/"); 
} 

public void doSomething(IEndPoint endpoint) { 
    ... 
} 

之所以一个人不能在你希望在相关合同中枚举将通过.equals(object)并通过==等于两者的方式继承。如果你可以继承,这是否有意义?

if ((DefaultEndPoints)JP_END_POINT == (DefaultServiceEndPoints)JP_END_POINT) { 

} 

,如果你说“是”,那么我希望能够做到这一点

DefaultEndPoint someEndpoint = DefaultServiceEndPoints.JP_END_POINT; 

这将留下一个门打开的错误,因为不能保证在一个ENUM注册枚举声明在另一个枚举声明中。

它会不一样吗?也许吧,但事实并非如此,改变它肯定会引入很多必须彻底思考的复杂问题(或者它会打开通往Java强大的静态类型检查的途径)。

0

这样的模式对你有吸引力吗?我让enum实现了一个interface并在调试集和发布集中实现接口。然后发布集可以从enum名称中得到属性名称 - 这是整洁的。

public interface HasURL { 
    public String getURL(); 
} 

public enum DebugEndPoints implements HasURL { 
    NA, 
    EU, 
    JP, 
    CN; 

    @Override 
    public String getURL() { 
    // Force debug to go to the same one always. 
    return "http://Debug.com/"; 
    } 
} 

public enum NormalEndPoints implements HasURL { 
    NA, 
    EU, 
    JP, 
    CN; 
    final String url; 

    NormalEndPoints() { 
    // Grab the configured property connected to my name. 
    this.url = getProperty(this.name()); 
    } 
    @Override 
    public String getURL() { 
    return url; 
    } 
}