转换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
确定类型是否足够兼容。