2016-10-09 94 views
1

我正在使用标准化Web服务的客户端上工作,但其中一个供应商的行为稍有不同,因此我们必须考虑这些行为。要做到这一点,我们一直在使用一个枚举:使用基础枚举作为依赖枚举的默认值

public enum ServiceProviderType { 
    FOO, BAR; 

    public ServiceProviderType checkService(String url) { 
     if (url.equals("http://www.example.com")) { 
      return ServiceProviderType.FOO; 
     } else { 
      return ServiceProviderType.BAR; 
     } 
    } 
} 

在这些行为的差异,根据我们从服务请求也不同,例如,我们可能会请求一个层,想那层红色,但知道BAR和FOO服务以不同的方式表示RGB值。为此,我们创建了另一个枚举,该枚举存储了服务中每个图层所需的属性。

public enum LayerServiceProviderType { 
    FOO("#ff0000"), 
    BAR("#ff5555"); 

    private String colour; 

    public ServiceProviderType(String colour) { 
     this.colour = colour; 
    } 

    public String getColour() { 
     return colour; 
    } 

    public ServiceProviderType checkService(String url) { 
     if (url.equals("http://www.example.com")) { 
      return ServiceProviderType.FOO 
     } else { 
      return ServiceProviderType.BAR; 
     } 
    } 
} 

这工作正常,除了当我们想要处理多个图层并将它们视为所有衍生的相同的基本枚举。实质上,我们想要将Layer1ServiceProviderType.BAR处理为等同于Layer2ServiceProviderType.BAR。但我们不能将枚举子分类,甚至试图这样做似乎打破了各种声音设计原则。

我首先想到的是有一个包含一个枚举的接口:

interface ServiceProvider { 
    ServiceProviderType {FOO, BAR}; 

    ServiceProviderType getServiceProviderType(); 

    ServiceProvider checkService(String url); 
} 

public enum LayerServiceProvider implements ServiceProvider { 
    FOO (ServiceProviderType.FOO, "#ff0000"), 
    BAR (ServiceProviderType.BAR, "#ff0000"); 

    public LayerServiceProvider(ServiceProviderType serviceProviderType, String colour) { 
     this.serviceProviderType = serviceProviderType; 
     this.colour = colour; 
    } 

    @Override 
    public ServiceProviderType getServiceProviderType() { 
     return this.serviceProviderType; 
    } 

    @Override 
    public ServiceProvider checkService(String url) { 
     if (url.equals("http://www.example.com")) { 
      return LayerServiceProviderType.FOO 
     } else { 
      return LayerServiceProviderType.BAR; 
     } 
    } 
} 

但似乎过度紧张的我有一个枚举与枚举每个持有相同值的范围。有一个更好的方法吗?

+0

任何原因,你不能仅仅加上'colour'到'ServiceProviderType'? – Andreas

+0

'colour'和其他变量对于每个'ServiceProviderType'都不是共同的 - 变量将根据我们从服务提供者请求的内容而改变。通用性是枚举。 – Michael

+0

真的不清楚你的问题是什么。这几乎不像关于问题领域规范和模型设计那样关于枚举问题。 “设计糟糕的API可能会永远毁掉一个班级 - J.布洛赫。也许一个枚举是一个优雅的路要走(策略枚举是一件事情),但也许不是。我对您的项目不熟悉,不知道如何提供帮助。 – scottb

回答

0

也许Visitor Pattern是你在找什么。

与enum一起使用时,它基本上允许不使用switch语句添加枚举相关逻辑。

例子:

public enum ServiceProviderType { 
    FOO { 
     @Override public <T> T apply(Action<T> action) { return action.doFoo(); } 
    }, 
    BAR { 
     @Override public <T> T apply(Action<T> action) { return action.doBar(); } 
    }; 

    public interface Action<T> { 
     T doFoo(); 
     T doBar(); 
    } 

    public abstract <T> T apply(Action<T> action); 

    public static ServiceProviderType checkService(String url) { 
     if (url.equals("http://www.example.com")) 
      return FOO; 
     return BAR; 
    } 
} 

public class LayerServiceProviderType implements ServiceProviderType.Action<String> { 
    @Override 
    public String doFoo() { 
     return "#ff0000"; 
    } 
    @Override 
    public String doBar() { 
     return "#ff0000"; 
    } 
} 

public class Main { 
    public static void main(String[] args) { 
     ServiceProviderType type = ServiceProviderType.checkService(""); 

     String colour = type.apply(new LayerServiceProviderType()); 
    } 
} 
+0

我喜欢这种模式,但我想知道它在LayerServiceProviderType需要返回多个变量的情况下如何工作。比如我可能需要一个'colour'变量和'name'变量(以及更多)的情况。 – Michael

+0

在这种情况下,你能想到的'层的...'类以上为*工厂类*,与设定的问题干将方法返回一个对象。它不限于只是getter方法;它可能是行为方法,使得它更像[策略模式](https://en.wikipedia.org/wiki/Strategy_pattern),基本上使用“工厂”来获得依赖于枚举的“策略”。 – Andreas