1

I'm trying to figure out the best way to solve a design issue. I have to be able to clone (I'm cloning them to Apache HttpClient) different types of HttpServletRequest (POST, GET...) and then send them. I want a super class with the common logic and then some subclasses for each method.

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);
}
}

Both HttpGet and HttpPost inherit from HttpUriRequest. Instead of having them as instance variables in subclasses, I could declare protected HttUriRequest request in superclass so it wouldn't be necesary to pass the instances to the superclass method all the time for common logic (as in protected void send(HttpUriRequest clonedRequest)). The problem is in ClonedPostRequest. The line httpRequest.setEntity(new StringEntity(sb.toString(), "UTF-8")); needs an instance of HttpPost and HttpUriRequest needs to be casted to it. It might be ok if it's only one time, but if you have this issue on serveral points, it might clutter the code with so much casting.

So my question was if is there a common pattern to approach this kind of design.

1 Answer 1

1

Three points:

  1. The implementation of "parallel specialisation" is a classic problem in strictly-typed OO languages
  2. I suspect your inheritance hierarchy of cloned requests is not the best way to model your problem anyway, but...
  3. even if you really need such a hierarchy, there are ways to solve it, e.g. using generics in Java.

I suspect you are really only specialising on the actual activity of cloning, not general specialisation of sub-types of (cloned) requests: your class naming hints at that. So I would rather abstract a RequestCloner concept, using generics to fix the sub-type casting problem, e.g.:

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)
    }
}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.