Pattern per condividere campi in ereditarietà

1

Sto cercando di capire il modo migliore per risolvere un problema di progettazione. Devo essere in grado di clonare (sto clonando loro in Apache HttpClient) diversi tipi di HttpServletRequest (POST, GET ...) e poi inviarli. Voglio una super classe con la logica comune e poi alcune sottoclassi per ogni metodo.

public abstract class ClonedRequest {

public ClonedRequest() {
    // Common logic
    ...
}

public static ClonedRequest GET() {
    return new ClonedGetRequest();
}

public static ClonedRequest POST() {
    return new ClonedPostRequest();
}

public abstract ClonedRequest clone(HttpServletRequest request);

public abstract void send();

protected void send(HttpUriRequest clonedRequest) {
// Common logic
...
}
}

public class ClonedGetRequest extends ClonedRequest {

private HttpGet httpRequest;

public ClonedGetRequest() {
    this.httpRequest = new HttpGet();
}

@Override
public ClonedRequest clone(HttpServletRequest request) {
    ...
}

@Override
public void send() {
    super.send(httpRequest);
}
}

public class ClonedPostRequest extends ClonedRequest {

private HttpPost httpRequest;

public ClonedPostRequest() {
    this.httpRequest = new HttpPost();
}

@Override
public ClonedRequest clone(HttpServletRequest request) {
    ...
    cloneBody(request);
}

private void cloneBody(HttpServletRequest request) {
    StringBuilder sb = new StringBuilder("");
    BufferedReader br = request.getReader();
    String line = "";
    while ((line = br.readLine()) != null) {
        sb.append(line);
    }
    br.close();
    httpRequest.setEntity(new StringEntity(sb.toString(), "UTF-8"));
}

@Override
public void send() {
    super.send(httpRequest);
}
}

Sia HttpGet che HttpPost ereditano da HttpUriRequest . Invece di averli come variabili di istanza in sottoclassi, potrei dichiarare protected HttUriRequest request nella superclasse, quindi non sarebbe necessario passare le istanze al metodo della superclasse tutto il tempo per la logica comune (come in protected void send(HttpUriRequest clonedRequest) ). Il problema è in ClonedPostRequest . La riga httpRequest.setEntity(new StringEntity(sb.toString(), "UTF-8")); ha bisogno di un'istanza di HttpPost e HttpUriRequest deve essere castata su di essa. Potrebbe essere ok se è solo una volta, ma se hai questo problema sui punti server, potrebbe ingombrare il codice con così tanto casting.

Quindi la mia domanda era se esiste un modello comune per avvicinarsi a questo tipo di design.

    
posta carcaret 26.06.2015 - 13:21
fonte

1 risposta

1

Tre punti:

  1. L'implementazione della "specializzazione parallela" è un problema classico nei linguaggi OO rigorosamente tipizzati
  2. Sospetto che la gerarchia ereditaria delle richieste clonate non sia il modo migliore per modellare il problema, ma ...
  3. anche se hai davvero bisogno di una tale gerarchia, ci sono modi per risolverlo, ad es. usando i generici in Java.

Ho il sospetto che tu stia davvero specializzandoti solo sulla attività effettiva della clonazione, non sulla specializzazione generale dei sottotipi di richieste (clonate): i tuoi suggerimenti per la denominazione della classe. Quindi preferirei astrarre un concetto di RequestCloner, usando i generici per risolvere il problema della trasmissione del sottotipo, ad esempio:

interface RequestCloner<T extends HttpUriRequest> {
    public T clone(T request);
}


class GetCloner implements RequestCloner<HttpGet> {

    @Override
    public HttpGet clone(HttpGet request) {
        //How to clone a GET request
        //(no casting needed, the generic T is fixed to an HttpGet)
        ...
    }
}


class PostCloner implements RequestCloner<HttpPost> {

    @Override
    public HttpPost clone(HttpPost request) {
        //how to clone a POST request
        //(no casting needed, the generic T is fixed to an HttpPost)
    }
}
    
risposta data 09.07.2015 - 08:54
fonte

Leggi altre domande sui tag