在客户端上设计请求桶信息

时间:2014-12-30 03:23:07

标签: java oop design-patterns

我试图找到设计"桶的客户端存储的最佳方式"。为了解释,服务器发送如下信息:

{
    'buckets': {
        'some_cool_bucket' : 'val1',
        'another_bucket' : 'name'
    }
}

值可以是

'some_cool_bucket' : 'val1' |  'val2' | 'val3'
'another_bucket' : 'name' | 'cool' | 'other'

基本上所有这些存储桶都是具有客户端和服务器都知道的所有可能值的枚举,尽管没有常见约束,例如存储桶可以具有任意数量的可能值(没有大小限制),以及任何命名方案

我正在努力克服Java,找到一个我很满意的设计。忘记解析JSON,等等等等,从设计的角度来看,我想知道我可以存储满足这些要求的数据:

  1. 每个存储桶都需要能够存储默认值,以防服务器没有发送一个
  2. bucket.isBucket(...)应该是类型安全的,即如果我们在这里使用枚举,你就不应该传入一个不属于错误的存储桶。
  3. 简单易用。 Buckets.some_cool_bucket.is(val1)将是理想的。
  4. 添加新桶时的最小锅炉板
  5. 非混淆设计
  6. 忽略这些要求,我们可以按如下方式实现:

    enum Bucket {
        some_cool_bucket('val1'),
        another_bucket('name');
    
        Bucket(String default) {
            [...]
        }
    
        // Assume this retrieves the stored value sent down from the server.
        String getVal() {
            [...]
        }
    
        boolean is(String val) {
            return getVal().equals(val);
        }
    }
    

    使用Bucket.some_cool_bucket.is('val1')。当然,我们希望通过更改is()的类型签名来扩展它,以接受some_cool_bucket定义的一些val枚举。由于存储桶可以采用的值不一致,因此我们必须在some_cool_bucket枚举中定义它。但是你不能在Java中的枚举中使用枚举。

    好的,重置。让我们再试一次:

    public abstract class BaseBucket<E extends Enum<E>> {
    
        private final Class<E> mClazz;
        private final E mDefaultBucket;
    
        public BaseBucket(Class<E> clazz, E defaultBucket) {
            mClazz = clazz;
            mDefaultBucket = defaultBucket;
        }
    
        // Assume this retrieves the stored value sent down from the server, uses
        // getName() to match with the data.
        protected E getVal() {
            [...]
        }
    
        protected abstract String getName();
    
        public boolean is(E test) {
            return getVal() == test;
        }
    }
    
    public class SomeCoolBucket extends BaseBucket<Val> {
        public SomeCoolBucket() {
            super(Val.class, Val.val1);
        }
    
        @Override
        public String getName() {
            return "some_cool_bucket";
        }
    
        public enum Val {
            val1, val2, val3;
        }
    }
    
    public Buckets {
        public static final SomeCoolBucket some_cool_bucket = new SomeCoolBucket();
    }
    

    好的,这很有效!大。它满足所有功能要求,但它很麻烦,我讨厌为每个桶创建一个新类。我发现很难证明所有代码的合理性,但我相信这些要求是合理的。

    有没有人有更好的解决方案?

1 个答案:

答案 0 :(得分:0)

在这种情况下,您可以使用抽象的BaseBucket类,但删除泛型位。基类可以具有Enum类型的实例变量。要在没有泛型的情况下执行此操作,您可以使用Strategy设计模式。使用此功能,您可以使所有Enum类型实现通用接口。为了举例,您可以调用此IBucketEnum。因此,您的BaseBucket类将具有IBucketEnum类型的实例变量,并且看起来像这样:

public abstract class BaseBucket{
    private IBucketEnum enum;
    //other instance vars

    public String getName(){
        enum.getName();
    }
}

从那里你可以有不同版本的BaseBucket,它们将具有从基础版继承的实现和实例变量,但是可以使用你需要的其他东西进行扩展。 希望这会有所帮助。