0

在netty中,MessageEvent(消息的包装器)有一个方法Object getMessage()可以从网络中获取真正携带的消息。阅读源代码我注意到他们大量使用instanceof运算符在方法之间切换。

但是,有各种各样的消息类型,我想避免这样的方法:

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
   if (e.getMessage() instanceof MessageType1) {
      ...
   } else if (e.getMessage() instanceof MessageType2) {
      ...
   } ... {
      ...
   } else if (e.getMessage() instanceof MessageTypeN) {
      ...
   } else {
      ctx.sendUpstream(e);
   }
}

利用多态性编写不同的方法会好得多,例如:

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
   // MessageType implements Message
   if (e.getMessage() instanceof Message) {
      handleMessage(ctx, (Message) e.getMessage());
   } else {
      ctx.sendUpstream(e);
   }
}

void handleMessage(ChannelHandlerContext ctx, MessageType1 m) {
    ...
}

...

void handleMessage(ChannelHandlerContext ctx, MessageTypeN m) {
    ...
}

但由于向下转换的限制,我不能。有没有一种干净的方法可以做到这一点,或者我是否与instanceof级联有关?我可以使用 Message 子类型中的 .doSomething() 方法将逻辑带出处理程序,但我想将业务逻辑保留在 netty 管道中。

4

1 回答 1

0

解决了应用访客模式:

public interface Handler {
    void handleMessage(ChannelHandlerContext ctx, MessageType1 m);
    void handleMessage(ChannelHandlerContext ctx, MessageType2 m);
    ...
    void handleMessage(ChannelHandlerContext ctx, MessageTypeN m);
}

然后:

@Sharable
public class MessageHandler extends SimpleChannelHandler implements Handler {
   ...
   @Override
   public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
     if (e.getMessage() instanceof Message) {
        Message m = (Message) e.getMessage();
        m.handleTo(ctx, this);
    } else {
        ctx.sendUpstream(e);
    }
}

@Override
public void handleMessage(ChannelHandlerContext ctx, MessageType1 m) {
    ...
}

public interface Message {
   /*
    * Will be {
    *    handler.handleMessage(ctx, this);
    * }
    * everywhere.
    */
   void handleTo(ChannelHandlerContext ctx, Handler handler);
}
于 2013-04-22T10:30:49.303 回答