2016-11-02 41 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建议的策略可以解决问题。