1

根据用例,这就是我们所做的:

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

我的代码有两个地方看起来很脏:

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. 是的,我们可以在一开始就修改这些对象(如果这就是您所说的“实现”)。因为,我们可以改变这一点,如果需要,我可以让它们共享一个通用接口。

谢谢,

4

1 回答 1

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!
于 2013-10-28T13:29:01.837 回答