Supponiamo di avere un'interfaccia di callback esistente con più metodi. Per illustrare il mio punto, utilizzo una richiamata che appaia nel codice che esegue alcune operazioni client HTTP:
public interface GetCallback<T> {
public void onSuccess(T data);
public void onAuthFailure();
public void onError(RequestError error);
//Potentially more methods like onPreGet etc...
}
E un metodo che effettua una richiesta richiederebbe un'istanza di questo callback come argomento:
public void issueRequest(String url, GetCallback<T> callback) {
// Implementation ...
}
Come ovvio, questo soffre di verbosità nel sito di chiamata:
public void getData(){
issueRequest("http://programmers.stackexchange.com", new GetCallback<String>(){
public void onSuccess(String data) {/*Do Something*/}
public void onAuthFailure(){/*Ask for credentials*/}
public void onError(RequestError error){/*Show error message*/}
});
}
Ho qualcosa di simile nel mio codice e ha funzionato bene. Uso una classe DefaultGetCallback
che fornisce l'implementazione predefinita dei metodi onAuthFailure
e onError
poiché l'azione che voglio eseguire in questi casi è praticamente la stessa indipendentemente dalla risorsa che sto richiedendo.
La domanda è, ha senso rifattorizzare questo in una classe composta da un insieme di interfacce a metodo singolo per trarre vantaggio dalla sintassi lambda?
public class GetCallback<T>{
public interface OnSuccessListener<T> {
public void onSuccess(T data);
}
public interface OnAuthFailureListener {
public void onAuthFailure();
}
public interface OnErrorListener {
public void onError(RequestError error);
}
private OnSuccessListener mSuccess;
private OnAuthFailureListener mAuthFailure;
private OnErrorListener mError;
public GetCallback<T>(OnSuccessListener<T> success) {
this.mSuccess = success;
}
public GetCallback<T> withAuthFailure(OnAuthFailureListener authFailure){
this.mAuthFailure = authFailure;
return this;
}
public GetCallback<T> withError(OnErrorListener error){
this.mError = error;
return this;
}
}
Potrei usare un pattern Builder per costruire il GetCallback
qui, ma questo è oltre il punto. Il sito di chiamata ora diventa:
public void getData(){
issueRequest(
"http://programmers.stackexchange.com",
new GetCallback<String>(s -> doSomething(s))
.withAuthFailure(() -> askForCredentials())
.withError(error -> showErrorMessage(error))
);
}
Un vantaggio è che posso personalizzare il comportamento dei singoli "eventi" (successo, errore ecc.) in isolamento, sul sito di chiamata, piuttosto che dover sottoclasse o creare una classe interna anonima.
Ma allora, quanto è troppo? Soprattutto dato che il mio attuale design mi ha già servito bene?