2016-11-02 39 views
3

假設我有一個應用程序負責接收供應商消息並轉換爲規範消息。例如:用於轉換Java對象的最佳實踐/模式

public class MessageA extends VendorMessage { ... } 
public class MessageB extends VendorMessage { ... } 

public class MessageX extends CanonicalMessage { ... } 
public class MessageY extends CanonicalMessage { ... } 

其中MessageA映射到MessageX和MessageB映射到MessageY。

我的方法是每個消息類型都有一個轉換器類來處理這種轉換。在這個例子中,我會有以下變形金剛:

public class MessageXTransfomer() 
{ 
    public MessageX transform(MessageA message) {...} 
} 

public class MessageYTransfomer() 
{ 
    public MessageY transform(MessageB message) {...} 
} 

我的問題與我最終會調用變形金剛的方式是一致的。

由於我的過程需要一些VendorMessage作爲輸入,所以我需要詢問該類型,以便知道指向哪個特定轉換器。例如,一種方法可能是這樣的:

public class TransfomerService 
{ 
    MessageXTransformer messageXTransformer = new MessageXTransformer(); 
    MessageYTransformer messageYTransformer = new MessageYTransformer(); 

    public CanonicalMessage transform(VendorMessage message) 
    { 
     if (message instanceOf MessageA) 
     { 
      return messageXTransformer.transform((MessageA) message); 
     } 
     else if (message instanceOf MessageB) 
     { 
      return messageYTransformer.transform((MessageB) message); 
     } 
    } 
} 

我不知道爲什麼,但我這種方法只是覺得很奇怪 - 因爲如果我做錯了什麼。對於我應該使用的這類問題,是否有最佳做法?

注意:我正在尋找最好的方法,而不使用任何轉換框架等。理想情況下,只使用基本Java即可實現該模式。

+0

正統的OO答案是向VendorMessage添加一個方法,將其轉換爲CanonicalMessage ...我認爲經典的重構類似於'convert conditional to polymorphism'或類似的東西。但實際考慮可能勝過這一點。做「可能有效的最簡單的事情」。不要過分複雜的事情。關注簡單性和可讀性。 –

+1

@john_omalley不同意。作爲一種短信解決方案,在消息中有一種方法可以很好地工作,但長期來看,1)您將供應商消息域與您的規範消息域耦合在一起2)如果您根本無法修改供應商消息並且它即將到來從一個單獨的系統? 3)當你開始注入轉化所需的東西時,你的方法立即停止工作(你不會注入消息,對嗎?) –

+0

@john_omalley還有一件事:它違背了單一責任原則:)消息不應該是負責任的將自己轉化爲某種東西。它應該是專用組件的責任。 –

回答

4

我喜歡@javaguy的答案,但它不完整。當然,這將是很好,如果你可以在他後面的例子使用特定的變壓器一樣,但如果你不能,你必須堅持TransformerFacade和怎樣的一個策略模式的:

public class TransformerFacade { 

    private Map<Class, VendorMessageToCanonicalMessageTransformer> transformers = new HashMap<>(); 
    { 
     // this is like strategies, the key may be class, class name, enum value, whatever 
     transformers.put(MessageA.class, new MessageXTransformer()); 
     transformers.put(MessageB.class, new MessageYTransformer()); 
    } 

    public CanonicalMessage transform(VendorMessage message) { 
     return transformers.get(message.getClass()).transform(message); 
    } 
} 
+1

調度在Java中不起作用,因爲Java沒有多次調度 –

+0

@FedericoPeraltaSchaffner謝謝,我認爲它的工作原理,但只是檢查,你是對的,從答案中刪除該部分! –

+0

我已經upvoted你的答案了:) PS如果你想在Java中使用這種派遣,你必須模擬一些訪客方法的雙派遣 –

1

我只想讓每一個具體的VendorMessage返回其對應的CanonicalMessage通過實現一個接口:

public interface Mapper<T> { 

    T map(); 
} 

然後,MessageA應該實現此接口:

public MessageA implements Mapper<MessageX> { 

    @Override 
    public MessageX map() { 
     MessageX message = ...; 
     // fill message 
     return message; 
    } 
} 

如果您不想在VendorMessage課程中進行映射,那麼在his answer中,Vadim Kirilchuk建議的策略可以解決問題。