Scenario di gestione degli errori di ereditarietà di Java

3

Ho cercato diversi posti per alcuni consigli su come risolvere questo problema prima di fare questa domanda, ma non sono riuscito a trovare qualcosa di simile a questo.

Quindi ho il seguente scenario in Java Spring Integration

Diciamo che ho un tipo di super-classe

class Foo {
    private String error;
    public Foo(error) {
       this.error = error;
    }
    public boolean isError(){
       return !(error.equals("SUCCESS"));
    }
 }

e quindi alcune sottoclassi

class Bar extends Foo {
    private String name;

    public Bar(String name) {
        this.name = name
        super("SUCCESS");
    }

    public String getName(){
        return name;
    }
    // more methods
 }

E ci sono più classi che sono sottoclassi di Foo ciascuna con metodi diversi. Ora ho un gateway di integrazione Spring che restituisce il supertipo Foo, con una rotta che contatta diversi endpoint e restituisce una sottoclasse diversa di Foo in base alla richiesta, o in alcuni casi un errore che in realtà è un'istanza di Foo che contiene la stringa di errore . L'errore deriva dal gestore degli errori delle facciate.

public interface Facade {
   Foo facadeMethod(Map<String, String> requestMap);
}

public class ErrorHandler {
   // arguments not important hence "..."
   public Foo handle(...) {
        return new Foo("ERROR");
   }
}

Il modo in cui attualmente sto gestendo questo è:

Foo response = facade.facadeMethod(requestMap);
if (response.isError()) {
  // do something
}
Bar bar = (Bar)response;
String name = bar.name();
// something with bar methods

È garantito che se isError è false, il tipo I downcast in realtà è del tipo sottoclasse. Il percorso è selezionato in base a una coppia chiave / valore in requestMap .

Potrei lanciare un'eccezione invece di avere un codice di errore, ma ho ancora lo stesso problema di dover downcast poiché la facciata deve restituire un tipo più generale (super-classe). Non vedo come utilizzare i generici per risolvere questo problema, poiché il metodo di facciata non è nella gerarchia di ereditarietà di Foo / Bar e delle altre sottoclassi. Ho anche pensato di usare una fabbrica ma non ho visto come usarla.

Tutto ciò sembra disordinato e vorrei evitare il downcasting. Esiste un modo per fare pratica in Java più pulita e migliore o sono bloccato con downcasting? Forse mi manca qualcosa di ovvio qui.

    
posta dylan7 09.11.2018 - 14:45
fonte

1 risposta

1

Potresti usare il seguente meccanismo: non hai if s, niente generici, niente cast, nessuna variabile pericolosa e una risposta typesable.

interface Response {
  void handle(Feedback feedback);
}

interface Feedback {
  default void onSuccess(Success success) {}
  default void onError(Error error) {}
}

class Success implements Response {
  String name;
  Success(String name) { this.name = name; }
  String name() { return name; }
  public void handle(Feedback feedback) {
    feedback.onSuccess(this);
  }
}

class Error implements Response {
  public void handle(Feedback feedback) {
    feedback.onError(this);
  }
}

Quindi, usalo in questo modo:

Feedback feedback = new Feedback() {
  public void onSuccess(Success success) {
    String name = success.name();
    // Do something with Success methods
  }
  public void onError(Error error) {
    // Do something with Error methods
  }
};
Response response = facade.facadeMethod(requestMap);
response.handle(feedback);

Note:

  • Ho rinominato Foo in Response e Bar in Success per la chiarezza della risposta.
  • Mi sono liberato della tua implementazione del meccanismo di errore perché era gestito meglio in questo modo. La "garanzia" richiesta ora deriva dalla distinzione in due diversi metodi di feedback: onSuccess e onError .
  • Può essere esteso creando nuovi sottotipi Response e nuovi metodi on... . Ovviamente puoi chiamare lo stesso metodo on... per due risposte diverse: è responsabilità della risposta chiamare il metodo appropriato del feedback.
risposta data 15.11.2018 - 10:34
fonte

Leggi altre domande sui tag