2011-01-26 16 views
5

Antecedentes rápidaCómo decorar un objeto en Java

tengo dos listas de (grandes) POJOs ser pasados ​​a un método en el que necesito para garantizar la singularidad a través de las dos listas. La mejor solución que puedo ver es construir dos conjuntos y verificar que su intersección esté vacía.

El problema

Para el contexto de este método, y este método solo, tengo que reemplazar el método de los POJOs en cuestión equals y hashcode.

lo que estoy buscando

Este parece ser un primer candiate para decorar los objetos existentes. Miré Guava's ForwardingObject pero parece ser el más adecuado para delegar objetos que implementan una interfaz determinada, que no es mi caso. En general, estoy buscando una solución que ...

  1. Evita hacer frente a todos los campos en el gran POJO (copia constructores).
  2. fácil de entender y mantener
  3. evita la creación de toda una nueva clase que extiende el POJO por el bien de éste método
+0

¿Quiere decir que los POJOs no implementan actualmente iguales y código hash ya y no se puede cambiar para que lo hagan? –

+0

El patrón de decorador realmente no tiene demasiado sentido sin una interfaz común. La extensión de la clase es "¡puaj!" –

+0

@Eric: No, estoy diciendo que los iguales y el código hash de POJO no tienen sentido para este único método. Extraño quizás, pero no es la primera vez que he querido definir una igualdad consciente del contexto. –

Respuesta

3

me acaba de ir con una clase contenedora.

crear una nueva clase que se crea una instancia con su POJO en el constructor. No copia el POJO, solo se aferra a la referencia al original. Luego escriba equals y hashcode como quiera en esa clase contenedora.

Algo como esto:

public class MySpecialWrapper{ 
    private final BigPojo delegate; 

    public MySpecialWrapper(BigPojo pojo){ 
    this.delegate = pojo; 
    } 

    public int hashCode(){ 
    //insert special impl here. 
    } 

    public boolean equals(Object o){ 
    //insert special impl here. 
    } 
} 

casos poso de la clase contenedora en sus series y el uso que de la verificación singularidad. Agregue un método de acceso (getDelegate) si necesita acceder al POJO ofensor en caso de falla.

+1

Parece bastante similar a la respuesta de Eric, por favor, vea mi comentario allí también. –

+1

No tengo conocimiento de nada que pueda hacer esto por usted. Sin embargo, como pueden ver, esto es bastante pequeño. Pon un buen comentario en la parte superior para aclarar para qué sirve esto, y deberías ser dorado. Respeto la búsqueda de la reutilización de lo que ya está definido. Pero, para algo como esto, debes sopesar eso con el tiempo invertido en la búsqueda de la respuesta. – rfeak

0

Puede utilizar un proxy dinámico para envolver cada elemento:

class VeryBigPOJO {} 

interface PojoWrapper { 
    VeryBigPOJO getPojo(); 
} 

class MyHandler implements InvocationHandler { 
    private VeryBigPOJO ob; 

    public MyHandler(VeryBigPOJO ob) { 
     this.ob = ob; 
    } 

    public Object invoke(Object proxy, Method method, Object[] args) 
      throws Throwable { 
     if(method.getName().equals("getPojo")) 
      return ob; 
     if(method.getName().equals("equals")) 
      //calculate equals 
     if(method.getName().equals("hashCode")) 
      //calculate hashCode 
    } 
} 

Luego envuelva sus objetos en estos proxies dinámicos:

VeryBigPOJO pojo = ...; 
PojoWrapper wrapper = Proxy.newProxyInstance(MyHandler.class.getClassLoader(), new Class[] { PojoWrapper.class}, new MyWrapper(pojo)) 

Y ahora puede agregar sus objetos wrapper a ese HashSet.

Sin embargo, ¿no sería más fácil de construir una, inmutable id objeto más pequeño de la gran POJO? Sin duda sería más legible.

2

Una solución sencilla es crear una clase contenedora para cada clase POJO. El contenedor contiene una referencia a la instancia POJO y define los métodos equals y hashcode que calculan sus valores en función de los campos apropiados en el POJO. Entonces puedes usar las clases normales de Colecciones.

+0

Estoy empezando a pensar de la misma manera. Esto puede ser trivial, pero ¿hay una clase de contenedor predefinida? Me gusta reutilizar lo que ya existe para facilitar la comprensión y la integridad. –

+0

+1 Como dije, ni siquiera tiene que envolverlo, puede precalcular el valor 'hashCode()' y un identificador que se comparará en 'equals()'. – biziclop

+0

@Andrew: Verdaderamente, para su caso una envoltura es la solución más simple. No estás creando un delegado. Como dijo @biziclop, puede calcular los valores que necesita directamente en el constructor. Y no necesariamente tiene que incluir todas las propiedades en sus cálculos, solo lo que sea exclusivo del objeto. Entonces el envoltorio no tiene que ser muy complejo. Podrías ir más allá e implementar la interfaz Comparable y usar el contenedor para ordenar, si eso es útil. Asegúrese de seguir los consejos de los Artículos 7 y 8 en Effective Java ... –

Cuestiones relacionadas