【问题标题】:design for multiple message types, but subclasses all do the same thing为多种消息类型设计,但子类都做同样的事情
【发布时间】:2017-07-17 06:17:04
【问题描述】:

我查看了这个问题的答案:Design pattern for handling multiple message types

我也在一条类似的船上。我的不同之处在于,我使用的是无法更改的现有 protobuf 架构。 protobuf 模式确实具有 messageType 属性。生成的代码看起来像

TradeMessage.parseFrom(byte[] bytes)
OtherMessage.parseFrom(byte[] bytes)
AnotherMessage.parseFrom(byte[] bytes)

所以现在我有一个工厂模式,当消息进入接收器时

MessageReceiver.java

Object parser = messageParserFactory.getParser(messageType);

获取解析器的类型

MessageParserFactory.java

public MessageParser getParser(int messageType) {
    if (messageType = Constants.TRADE_MESSAGE) {
        return new TradeParser();
    } else if (messageType = Constants.OTHER_MESSAGE) {
        return new OtherParser();
    }
    return null;
}

基本上对所有不同的消息类型重复工作,基本上只是包装生成的 parseFrom 方法。

public interface MessageParser {
    void doParse(byte[] bytes);
}

TradeParser.java
public void doParse(byte[] bytes) {
    TradeParser.parseFrom(bytes);
}

OtherParser.java
public void doParse(byte[] bytes) {
    OtherParser.parseFrom(bytes);
}

AnotherParser.java
public void doParse(byte[] bytes) {
    AnotherParser.parseFrom(bytes);
}

它可以工作,但有更好的方法吗,因为基本上我为每种消息类型创建的所有解析器都做完全相同的事情,只需调用parseFrom

【问题讨论】:

  • 您需要MessageParser 吗?为什么不直接返回解析后的实例?
  • messageType = 应该是 messageType ==。我认为这只是一种伪代码?
  • 另外,如果 null 是不受支持的消息类型,请不要返回,抛出异常。
  • @AndyTurner 不,我根本不需要消息解析器。这只是为了整理客户的主要入口点。实际上,我可以只为消息类型设置一个 switch 语句,然后返回解析后的对象。
  • @Michael ya 只是所有的伪代码。谢谢。

标签: java


【解决方案1】:

您会拥有大量的消息类型吗?你的信息复杂吗?

无论如何,我明白您为什么认为这是不必要的,因为您现在只是在包装您的 parseFrom 方法。如果您的解析变得复杂而不仅仅是对 parseFrom 方法的调用,这可能会变得有趣。

目前,您最好存储一个 key-value 数组,其中 messageType 为 key,Class 为 value,然后使用反射来实例化您的消息?

我认为这可能相当干净,因为您可以在上下文/配置文件中定义您的数组。

【讨论】:

  • 消息类型的数量将少于 20。除了解析消息之外,我在解析器中没有看到太多逻辑。逻辑在应用程序的另一个区域。
  • 我将如何通过反射来做到这一点?是否有任何性能成本,因为每次从客户端传入消息时,都必须使用该权限才能获取 messageParser。
  • 是的,通过反射进行实例化会产生巨大的性能成本。但是,我假设您的 parseFrom 方法可能是静态的,并且我相信对静态方法的调用更便宜。无法记住来源,因此请谨慎使用此声明,甚至更好,测试一下!在逻辑上,您必须查看您的数组,获取与您的消息类型关联的类,然后使用反射调用您的 parseFrom。它将类似于: Method m = clazz.getMethod("name", argTypes);对象 o = method.invoke(null, args);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多