2013-10-28 109 views
1

按照一個用例,這是我們做什麼:設計按對象類型

  1. 暴露多個不同的參數(如InputObject1,InputObject2等。)Async服務的API。
  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. 是的,我們可以在開始時修改這些對象(如果這就是你的意思是「實現」)。因爲,我們可以改變這一點,如果需要,我可以讓他們共享一個共同的界面。

感謝,

+0

不錯,那麼你可以考慮我的建議! – A4L

回答

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! 
+0

在「編輯」部分回答了您的問題。 – instanceOfObject

+0

如果我沒有錯,getQueueTask()在你的情況下會從隊列中取一個任務並調用相應的可運行類。我對這部分更感興趣。我們如何讓特定班級打電話給? 另外,將從隊列接收到的Json轉換爲對象類型(用細節修改了問題)。 – instanceOfObject

+0

@instanceOfObject檢查我的編輯! – A4L