2010-11-27 16 views
5

Estoy utilizando el patrón de diseño Chain of Responsibility en Java. La cadena como un todo representa una solicitud de objetos de ciertos tipos. Cada "Manejador" en la cadena es responsable de manejar las unidades solicitadas de 1 tipo. Todas las solicitudes se manejan esencialmente de la misma manera, así que traté de hacer que la clase "Handler" fuera genérica. Así que en la clase manija Necesito un método como este (el manejo en sí se simplifica, ya que sólo ofuscaría mi problema):controlador de cadena de responsabilidad con java generics

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

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

El problema es que un instanceof como esto es imposible. Porque el tipo T no se almacena explícitamente durante el tiempo de ejecución (o eso es lo que entendí durante mi investigación en Internet). Entonces mi pregunta es: ¿cuál es la mejor alternativa?

Respuesta

2

implementar controladores utilizando los genéricos mediante el uso de un parámetro de constructor para definir la clase del controlador es compatible con:

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); 
     } 
    } 

    // ... 
}  
+0

de hecho ... funciona para un nivel de objeto más alto, pero los genéricos parecen predeterminados para 'Objeto' en las firmas de métodos en tiempo de compilación. De todas formas. La segunda solución se eliminó, pero la primera solución aún se adapta bien a lo que está tratando de lograr –

+0

esto es lo más cercano a la solución que quería lograr, gracias. Ahora puedo soltar la parte genérica, porque puedo hacer todo con la Clase como argumento – Ingdas

1

Sería feo, pero se puede intentar esto:

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(); 
} 
+0

+1 - Funciona, y no es realmente tan feo. –

+0

¿No se define 'getClass' como' public' en 'java.lang.Object'? Parece que estás tratando de anularlo con un nivel de acceso más estricto. –

+0

Y si elige un nombre diferente, entonces 'Class' debe tener un parámetro de tipo:' protected abstract Class getHandledValueType(); ' –

1

Parece que no está realmente utilizando una cadena en absoluto, a menos que tenga algunos casos en los que tanto la base y sub clases inicio a los eventos . Si eso menos parte no se aplica, usted podría hacer algo como

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

y en el controlador de la raíz:

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

No tiene sentido tener un controlador utilizando los genéricos si se llama a manejar el cada objeto De cualquier se instancia un controlador para el tipo de esta manera:

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

    public void handle(T O){ 
    ... 
    } 
} 

o se define un controlador de clase abstracta y dejar que la subclase específica para manejar el tipo específico o simplemente pasar el caso a la cadena. También usando

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

es realmente un anti patrón y se puede romper las reglas de POO.

Cuestiones relacionadas