2017-04-17 19 views
0

我有2級的應用:application_1applicaion_2如何用多態性替換交換機?

appplication_1發送不同類型的消息,以application_2

有幾種類型。我可以聲明這些類型的枚舉。

enum MessageType{ 
    TYPE_1, 
    TYPE_2, 
    ... 
} 

在application_2框架我用的建議我寫下面的API

public void handle(Object o){ 
    //logic 
} 

我想了解如何構建類來分別處理每個消息。

我明白,我可以爲所有郵件聲明常見類型:

abstract class AbstractMessage{ 
    MessageType type; 
    Object o; 
    //... 
} 

application_2內把手,我可以寫水木清華這樣的:

MessageType mt = ((AbstractMessage) o).getType(); 
    switch(mt){ 
    case TYPE_1: 
     //handle TYPE_1 
     break; 
    case TYPE_2: 
     //handle TYPE_2 
     break; 
     .... 
    } 

但這個代碼看起來醜陋。

請幫助找到更好的解決方案。

+1

@Downvoter,請解釋一下你不明白的地方。我準備好改進我的問題。我真的努力問清楚的問題 – gstackoverflow

+0

看起來你在尋找的是[策略模式](https://en.wikipedia.org/wiki/Strategy_pattern#Java)。 –

+0

@Thomas Fritsch,可能會但你能提供更多的細節? – gstackoverflow

回答

0

application_2無論如何將需要知道它收到哪種類型的消息,所以某種switch是不可避免的。但關鍵是隻有在一個地方 。例如,你可以有方法類似以下內容:

public MessageHandler getHandlerFor(MessageType messageType) { 
    switch (messageType) { 
     case TYPE_1: return Type1MessageHandler(); 
     case TYPE_2: return Type2MessageHandler(); 
     ............ 
     default: throw new IllegalArgumentException("No handler found for messageType: " + messageType); 
    } 
} 

然後你需要的MessageHandler的對應於戰略模式層次:

public interface MessageHandler { 
    void handle(); 
} 

MessageHandler接口的每個產品都會提供MessageType特定的處理邏輯。

4

如果你想使用polymorfism你可以定義abstract消息類:

abstract class AbstractMessage { 
    public abstract void doStuff(); 
    //... 
} 

而不是使用enums,創建一個類擴展抽象類和重寫方法爲每個消息類型:

class Type1Message extends AbstractMessage { 
    @Override 
    public void doStuff() { 
     //handle TYPE_1 
    } 
} 

class Type2Message extends AbstractMessage { 
    @Override 
    public void doStuff() { 
     //handle TYPE_2 
    } 
} 

然後在您的handle方法:

((AbstractMessage) o).doStuff(); 
+2

我認爲'消息'本身不應該知道它將如何處理。客戶端代碼負責決定如何處理每種類型的消息。 –

+1

@PavloViazovskyy好吧,這取決於我的猜測;這也避免了OP所要求的「switch」 –

+0

看起來我們有2個層次結構。處理程序和消息。橋可以幫助嗎? – gstackoverflow

0

您可以使用chain-of-responsibility模式。它與策略模式的不同之處在於您的消息指示每個應用程序執行的命令。這基本上是switch正在做的事情。

你動態加載實現您的handle方法的接口類(帕夫洛的類與一些改裝工程將它與洛里斯抽象消息結合起來):

public interface MessageHandler 
{ 
    void handle (AbstractMessage msg); 
} 

Java有一個service provider這是一個概念動態加載方法(我敢肯定還有其他方法可以使用,如果這不符合你的需要)。您可以在處理消息時遍歷處理程序,將每個處理程序傳遞給消息實例。每個處理程序決定是否要處理該消息。如果你願意,你甚至可以讓handle返回一個boolean來表示鏈可以停止調用後續處理程序。

您可以在每個應用程序中爲要處理的消息類型實現處理程序。有很多方法可以解決這個問題(加載處理程序並在啓動時初始化,在消息處理時加載它們等),以便選擇適合您需求的方法。鏈接的服務提供商文章有一個簡單的循環來演示處理程序的加載。

不需要switch隨着您的代碼被修改而改變,您只需重新配置您的jar的構建方式。這也是open-closed principle的一個很好的例子,你的代碼不會改變,但是可以擴展。

0

也許像下面的東西。它確實有一個開關,但每種類型的代碼都在枚舉中。

public class So43459907 { 
    public enum Type { 
     m1 { 
      @Override Object create(Object o) { 
       return o; 
      } 
      @Override void handle(Object o) {} 
     }, 
     m2 { 
      @Override Object create(Object o) { 
       return o; 
      } 
      @Override void handle(Object o) {} 
     }; 
     abstract Object create(Object o); 
     abstract void handle(Object o); 
     public static Object create(Type type,Object o) { 
      switch(type) { 
       case m1: 
        return m1.create(o); 
       case m2: 
        return m2.create(o); 
       default: 
        throw new RuntimeException("oops"); 
      } 
     } 
    } 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
    } 
}