【问题标题】:chain-of-responsibility handler with java generics具有 java 泛型的责任链处理程序
【发布时间】:2010-11-27 14:29:55
【问题描述】:

我在 Java 中使用责任链设计模式。整个链代表对某些类型对象的请求。链中的每个“处理程序”负责处理请求的 1 种类型的单元。 所有请求都以基本相同的方式处理,因此我尝试使“处理程序”类通用。 所以在 Handle-class 我需要一个这样的方法(处理本身被简化了,因为它只会混淆我的问题):

public class Handler<T>{
   int required;
   Handler<?> next;

   public void handle(Object O){
      if(o instanceof T){
         required --;
      }else{
         next.handle(o);
      }
   }
}

问题是这样的 instanceof 是不可能的。因为类型 T 在运行时没有明确存储(或者这就是我在互联网上研究时所理解的)。所以我的问题是:最好的选择是什么?

【问题讨论】:

    标签: java design-patterns generics


    【解决方案1】:

    通过使用构造函数参数来定义处理程序支持的类,使用泛型实现处理程序:

    public class Handler<T> {
        private int required;
        private Handler<?> next;
        private Class<? extends T> c;
    
        public Handler(Class<? extends T> c) {
            this.c = c;
        }
    
        public void handle(Object o) {
            if (c.isInstance(o)) {
                required--;
            } else {
                next.handle(o);
            }
        }
    
        // ...
    }    
    

    【讨论】:

    • 确实......它适用于更高的对象级别,但泛型似乎在编译时的方法签名中默认为Object。反正。第二个解决方案已被删除,但第一个解决方案仍然适合您想要实现的目标
    • 这是最接近我想要实现的解决方案,谢谢。现在我可以放弃通用部分,因为我可以用 Class 作为参数来做任何事情
    【解决方案2】:

    看起来您实际上根本没有使用链,除非您在某些情况下基类和子类都启动事件。如果那除非部分不适用,你可以做类似的事情

    Map<Class, Handler> handlers = //...initialize however
    

    在根处理程序中:

    public void handle(Object o) {
     handlers.get(o.getClass()).handle(o);
    }
    

    【讨论】:

      【解决方案3】:

      如果您在每个对象上调用句柄,则使用泛型处理程序是没有意义的。 您可以为这样的类型实例化一个处理程序:

      public class Handler<T>{
         int required;
         Handler<?> next;
      
         public void handle(T O){
           ...
         }
      }
      

      或者您定义一个抽象类处理程序并让特定的子类处理特定类型或只是将事件传递给链。 也使用

      if( x.isInstance(o)) {...}
      

      确实是一种反模式,您可以打破 OOP 规则。

      【讨论】:

        【解决方案4】:

        这会很丑,但你可以试试这个:

        public abstract class Handler {
           int required;
           Handler next;
        
           public void handle(Object o){
              if(getMyClass().isInstance(o)){
                 required --;
              }else{
                 next.handle(o);
              }
           }
        
           protected abstract Class getMyClass();
        }
        

        【讨论】:

        • getClass 不是在java.lang.Object 上定义为public 吗?您似乎正在尝试使用更严格的访问级别覆盖它。
        • 如果你选择不同的名字,那么Class应该有一个类型参数:protected abstract Class&lt;? extends T&gt; getHandledValueType();
        • @Mike Samuel:更正了getClass() 问题,但第二件事只是使调用代码更加复杂(是的,更安全)。
        • 我只提出它是因为您会收到编译器警告。理性的人显然可能不同意如何处理警告,但我强烈建议在这样的库代码中使用类型参数,因为它可能会在多个客户端的代码中暴露错误。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-23
        • 2021-03-13
        • 2022-01-19
        • 1970-01-01
        相关资源
        最近更新 更多