¿Cómo preservas las interfaces cuando usas el patrón decorador?

Si los objetos que se decoran implementan diferentes combinaciones de otras interfaces, ¿cómo implementa un decorador sin perder los métodos de interfaz adicionales? Por ejemplo, supongamos que tenemos las siguientes clases e interfaces, donde I es la que nos interesa decorar y D es la implementación de un decorador:

class C1 implements I, I1, I2

class C2 implements I, I2, I3

class C3 implements I, I3, I4

class D implements I {
    I wrappedValue
    // Methods for I
}

Una vez que instanciamos una instancia de D con una I envuelta, que puede ser C1, C2 o C3, perdemos el acceso a los métodos adicionales para I1, I2, I3 e I4 que la envuelta puedo implementar.

Respuesta 1

Si C1, C2, C3 fueran interfaces, habrá una solución proxy.

interface C1 extends I, I1, I2

De lo contrario, necesitaría una biblioteca como cglib para decorar la clase.

Un proxy en combinación con un método genérico de fábrica conservará las otras interfaces, por lo que no necesita convertir el código:

class D<T_I extends I> implements InvocationHandler, I {

  public static <T_I extends I> T_I decorate(T_I wrappedValue) {
    return (T_I)Proxy.newProxyInstance(
        wrappedValue.getClass().getClassLoader(),
        getAllInterfaces(wrappedValue.getClass()),
        new D<T_I>(wrappedValue));
  }

  private static Class[] getAllInterfaces(Class type) {
    if (type.isInterface()) {
      Class[] all = new Class[type.getInterfaces().length + 1];
      int i = 0;
      all[i++] = type;
      for (Class t : type.getInterfaces()) {
        all[i++] = t;
      }
      return all;
    } else {
      return type.getInterfaces();
    }
  }


  private final T_I wrappedValue;

  private D(T_I wrappedValue) {
    this.wrappedValue = wrappedValue;
  }

  public Object invoke(Object proxy, Method method, Object[] args) {
    if (method.getDeclaringClass() == I.class) {
      // call wrapped method in D
      return method.invoke(this, args);
    }
    //call unwrapped method of other interface
    return methos.invoke(wrappedValue, args);
  }

  // Methods for I
}

Ahora puede usarlo de la siguiente manera:

C1 c1 = ...;
c1 = D.decorate(c1);
Respuesta: 2

La interfaz sería algo como esto.

interface I
{
   I objI {get;} // can hold reference to other objects of type I or null
   // If the requirement is to make setter as public, that should be fine as well.

   // You can have decorator related behavior here
   void DecoratorBehavior1(); 
   void DecoratorBehavior2(); 
}

la clase D no necesita realizar el ajuste. Lo que hace es implementar I.

class D implements I
{
  public I objI {get; private set;}
  // You can have other overloaded constructors as well
  D(I obj)
  {
     this.objI = obj;
  }
}

El objeto de tipo I contiene una referencia a otro objeto de tipo I o nulo. Este objeto puede implementar interfaces de otros tipos o puede derivarse de otras clases base.

Si desea utilizar métodos de otros tipos, puede convertir el objeto al tipo y uso respectivos. Antes de la conversión de texto, puede verificar si el objeto es de cierto tipo o no.

....
I objC1 = new C1(null);
I objC2 = new C2(objC1);
I objC3 = new C3(objC2);
I objD = new D(objC3);
...
I oGetBackC3 = objD.objI;
if(oGetBackC3 is typeof(C3))
{
   C3 oGotBackC3 = (C3)oGetBackC3;
   ...
   // You can now call C3 methods on object
}
....

He escrito un fragmento en C #, pero también puede seguir siendo igual para Java.

Respuesta: 3

Tengo una función en Jython, esta función usa Popen para ejecutar otro programa que escribe un archivo xml en su stdout, que se dirige a un archivo. Cuando finalice el proceso, cierro el archivo y llamo ...

Tengo un archivo XML con algunas etiquetas SOAP que quiero ignorar. Estaba analizando el archivo XML con pull-parser pero dejó de funcionar desde que aparecieron las etiquetas SOAP. El archivo XML se parece a: <? ...

Hii Estoy trabajando en una aplicación donde necesito mostrar imágenes de una carpeta seleccionada por un usuario. Todas las imágenes presentes en la carpeta deben mostrarse. Me gustaría saber cómo mostrarlas ...

Escribí un código que escribe objetos comprimidos en un archivo. Mi pregunta es: ¿hay alguna forma en que pueda realizar un seguimiento del incremento del tamaño de mi archivo a medida que se escribe el objeto? Aquí está mi código: ...