Soluzione alternativa per sovrascrivere un insieme limitato di metodi di un'interfaccia

0

Ho un'interfaccia che ha ~ 30 metodi e ha due diverse implementazioni.

Sto cercando di creare un'altra implementazione che avrà una logica personalizzata e a volte chiamerà una di quelle implementazioni esistenti a seconda di alcune condizioni.

Il problema è che voglio solo questo comportamento per un sottoinsieme di metodi, diciamo 10 metodi.

public interface ITest {

void method1(Param1 param1);
void method2(Param2 param2);

}

public class TestImpl1 implements ITest {
void method1(Param1 param1){
//
}
void method2(Param2 param2){
//
}
}

Diciamo che voglio solo sovrascrivere il metodo 1 nella nuova implementazione e che in alcuni casi potrebbe chiamare implementazione esistente.

Delegare la chiamata da una nuova interfaccia a quella esistente per method2 sembra un modo, ma non sono sicuro che sia l'opzione migliore. Qualsiasi idea sarebbe apprezzata per renderla più pulita.

Grazie!

    
posta instanceOfObject 07.11.2017 - 02:04
fonte

1 risposta

1

Il codice chiamerà i metodi che non stai implementando? In caso contrario, puoi semplicemente pubblicare UnsupportedOperationException . Poiché è un RuntimeException , verrà comunque compilato. Se il codice è che chiama i metodi che non si desidera implementare, è possibile implementare automaticamente tali metodi e delegare a un'implementazione esistente utilizzando InvocationHandler . Questo può essere conveniente perché la tua interfaccia è particolarmente lunga. Ad esempio:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestImpl1 implements InvocationHandler {
    private final ITest delegate1;
    private final ITest delegate2;

    public TestImpl1(ITest delegate1, ITest delegate2) {
        this.delegate1 = delegate1;
        this.delegate2 = delegate2;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        if (method.getName.equals("method1") {
            // choose delegate 1 or 2
            if (...) {
                method.invoke(delegate1, args);
            } else {
                method.invoke(delegate2, args);
            }
        } else {
            // for all other methods, delegate to delegate1
            method.invoke(delegate1, args);
        }
    }
}

Puoi usarlo in questo modo:

ITest delegate1 = ...
ITest delegate2 = ...
// instantiate a proxy
ITest testImpl1 = (ITest) Proxy.newProxyInstance(ITest.class.getClassLoader(),
            new Class[] { ITest.class },
            new TestImpl1(delegate1, delegate2));
// use
testImpl1.method1(...)
testImpl1.method2(...)
    
risposta data 07.11.2017 - 03:21
fonte