没有instanceof的Netty.io messageReceived覆盖

时间:2013-04-22 10:02:48

标签: java polymorphism netty instanceof visitor

在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()方法将逻辑输出到Handler,但我想将业务逻辑保留在netty管道中。

1 个答案:

答案 0 :(得分: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);
}