转换Java对象的最佳实践/模式

转换Java对象的最佳实践/模式,java,Java,假设我有一个应用程序,负责获取供应商消息并将其转换为规范消息。例如: public class MessageA extends VendorMessage { ... } public class MessageB extends VendorMessage { ... } public class MessageX extends CanonicalMessage { ... } public class MessageY extends CanonicalMessage { ... }

假设我有一个应用程序,负责获取供应商消息并将其转换为规范消息。例如:

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

public class MessageX extends CanonicalMessage { ... }
public class MessageY extends CanonicalMessage { ... }
其中MessageA映射到MessageX,MessageB映射到MessageY

我的方法是,每个消息类型有一个transformer类来处理这种转换。在本例中,我将使用以下变压器:

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即可实现该模式。

我喜欢@javaguy的答案,但它并不完整。当然,如果您可以像他后面的示例中那样使用特定的transformer会很好,但是如果您不能,您必须坚持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);
    }
}
公共类TransformerFacade{
私有映射转换器=新的HashMap();
{ 
//这就像策略一样,关键可能是类、类名、枚举值等等
transformers.put(MessageA.class,新的messagexttransformer());
transformers.put(MessageB.class,新的MessageYTransformer());
}
公共规范消息转换(VendorMessage消息){
返回transformers.get(message.getClass()).transform(message);
}
}

我只需通过实现一个接口,让每个具体的
供应商消息
返回其相应的
规范消息

public interface Mapper<T> {

    T map();
}
public MessageA implements Mapper<MessageX> {

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

如果您不想在
VendorMessage
类中进行映射,那么Vadim Kirilchuk在中建议的策略将起到作用。

正统的OO答案是向VendorMessage添加一个方法,将其转换为规范消息。。。我认为经典的重构类似于“将条件转换为多态性”之类的东西。但实际考虑可能胜过这一点。做“可能有效的最简单的事情”。不要把事情过分复杂化。关注简单性和可读性。@john_omalley不同意。作为一个短期解决方案,在消息本身中包含一个方法是很好的,但从长远来看1)您将供应商消息域与规范消息域耦合2)如果您根本无法修改供应商消息,并且它来自一个单独的系统,该怎么办?3) 当您开始注入转换所需的东西时,您的方法立即停止工作(您不打算注入到消息中,对吗?@john_omalley还有一件事:它打破了单一责任原则:)消息不应该负责将自身转换为某些东西。分派在Java中不起作用,因为Java没有多个dispatch@FedericoPeraltaSchaffner谢谢,我认为它是有效的,但只是检查,你是对的,删除了答案中的这一部分!我现在已经对你的答案投了赞成票:)PS如果你想在Java中使用这种分派,你必须用一些访问者方法模拟双重分派(同样如此;)是的,我开始忘记了所有企业的基本知识,访客很好,但不适合这种任务。我非常喜欢这种解决方案。我会用几个额外的选项来进一步完善它:1也许transformer对象可以提供一个“getMessageType”函数,这样它就可以说出它转换的类型——这意味着你只需要transformer对象就可以将它们正确地归档到地图中。2.不要使用确切的类型,而是使用责任链模式询问每个转换器“您能转换此消息吗?”并使用函数
isAssignableFrom
确定类型是否足够兼容。