设计以支持按对象类型的请求处理

时间:2013-10-28 12:47:39

标签: java oop asynchronous gson

根据用例,我们这样做:

  1. 使用不同的参数公开多个Async服务API(例如InputObject1,InputObject2等)。
  2. 客户端使用正确的输入类型调用这些API,然后将响应发送回客户端,并以JSON格式(使用Gson)将输入对象推送到队列(例如SQS)中。
  3. 另一个轮询器继续轮询队列并从队列接收消息。收到消息后,poller必须按照inputObject类型执行任务。
  4. 我的代码有两处看起来很脏:

    a. How to check the type of object on receiving from the queue? This would be in JSON format and I will have to convert JSON back to object. It will belong to one of the multiple potential objects.
    
    b. Once type is known, how to call class responsible to handle that object?
    

    这个用例的最佳设计是什么?

    For a), one option is to create a `RequestWrapper` containing all the objects and populating the one this message belongs to.
    

    我能为b)思考的几种方式如下:

    1. Add another parameter to the object and pass it to queue. Use this parameter to identify API called.
    2. Use `instanceof` to get exact requestObject using multiple if-else and do the needful.
    

    虽然,这些对我来说似乎不太整齐。还有更好的建议吗?

    ==Edit==
    

    @ A4L

    1. 不,他们不共享任何共同的界面(至少,截至目前)。

    2. 是的,我们可以在开始时修改这些对象(如果你的意思是“实现”)。因为,我们可以更改它,如果需要,我可以让它们共享一个公共接口。

    3. 谢谢,

1 个答案:

答案 0 :(得分:1)

我建议引入至少一个新接口QueueTaskAble,它将由您的输入对象实现,第二个 - 可选,可以简单地为java.lang.Runnable - 然后以某种方式执行任务runexecute方法。

以下是它的样子:

interface QueueTaskAble {
    Runnable getQueueTask();
}

class InputObjectFooQueueTask implements Runnable {
    @Override
    public void run() {
        // TODO Auto-generated method stub            
    }
}

class InputObjectFooImpl implements QueueTaskAble {
    @Override
    public Runnable getQueueTask() {
        return new InputObjectFooQueueTask();
    }
}

void processQueueInputObject(QueueTaskAble queueObject) {
    queueObject.getQueueTask().run();
}

修改

不幸的是,使用Gson无法将本地反序列化为接口。为了能够这样做,您需要实现一个类型适配器,您可以将其传递给GsonBuilder#registerTypeAdapter,以便正确地序列化和反序列化您的对象。

以下是你可以采取的措施:

类型适配器

public class GenericGsonTypeAdapter<T> implements JsonSerializer<T>, 
        JsonDeserializer<T> {

    @Override
    public JsonElement serialize(T src, Type typeOfSrc, 
                    JsonSerializationContext context) {
        JsonObject jo = new JsonObject();
        jo.addProperty("className", src.getClass().getName());
        jo.add("jsonData", context.serialize(src));
        return jo;
    }

    @Override
    public T deserialize(JsonElement json, Type typeOfT,
        JsonDeserializationContext context) throws JsonParseException {
        T obj = null;
        if(json instanceof JsonObject) {
            JsonObject jo = (JsonObject) json;
            JsonElement jeJson = jo.get("jsonData");
            if(jeJson != null) {
                JsonElement jeClassName = jo.get("className");
                try {
                    obj = context.deserialize(json,
                                Class.forName(jeClassName.getAsString()));
                } catch (ClassNotFoundException e) {
                    throw new JsonParseException(e);
                }
            }
        }
        return obj;
    }   
}

自定义Gson构建器(不幸的是GsonBuilder是最终的,因此无法扩展,因此作为静态最终成员)

public class InputObjectGsonBuilder {
    private final static GsonBuilder gb;
    static {
        gb = new GsonBuilder();
        gb.registerTypeAdapter(QueueTaskAble.class,
                    new GenericGsonTypeAdapter<QueueTaskAble>());
    }

    public Gson create() {
        return gb.create();
    }
}

示例队列

public class InputObjectGsonQueue {

    private Queue<String> queue = new ArrayDeque<>();

    public boolean pushInputObject(String json) {
        return queue.offer(json);
    }

    public void processQueue() {
        InputObjectGsonBuilder gb = new InputObjectGsonBuilder();
        String json;
        while(null != (json = queue.poll())) {
            QueueTaskAble queueTaskAble = gb.create().fromJson(json,
                               QueueTaskAble.class);
            processQueueInputObject(queueTaskAble);
        }
    }

    private void processQueueInputObject(QueueTaskAble queueObject) {
        queueObject.getQueueTask().run();
        // or for asynchronous processing
        // new Thread(queueObject.getQueueTask()).start();
    }
}

一些输入对象和任务实现

public class InputObjectFooImpl implements QueueTaskAble {
    @Override
    public Runnable getQueueTask() {
        return new InputObjectFooTaksImpl();
    }
}

public class InputObjectBarImpl implements QueueTaskAble {
    @Override
    public Runnable getQueueTask() {
        return new InputObjectBarTaksImpl();
    }
}

public class InputObjectFooTaksImpl implements Runnable {
    @Override
    public void run() {
        System.out.println("Foo!");
    }
}

public class InputObjectBarTaksImpl implements Runnable {
    @Override
    public void run() {
        System.out.println("Bar!");
    }
}

最后是一个示例应用程序

public class App {
    public static void main(String... args) {
        InputObjectGsonBuilder gb = new InputObjectGsonBuilder();

        InputObjectGsonQueue gq = new InputObjectGsonQueue();
        gq.pushInputObject(gb.create().toJson(new InputObjectFooImpl(), 
                    QueueTaskAble.class));
        gq.pushInputObject(gb.create().toJson(new InputObjectBarImpl(), 
                    QueueTaskAble.class));

        gq.processQueue();
    }
}

<强>输出

Foo!
Bar!