views:

70

answers:

4

I have two methods that do essentially the same thing, just with different types. I want to abstract out this functionality to some generic method and I think I could do it easily in C# with delegates, but I don't know the equivalent in Java. I'm just showing two of the methods here, but there are several (like eight) different makeWhateverRequest-style methods. Here are my methods:

public State makeGetRequest(User user, String name) {
    Get request = Builder.getGetRequest(user, name);
    GetResponse response = service.get(request);
    return ResponseTypeFactory.getResponseType(response);
}

public State makePutRequest(User user, String name) {
    Put request = Builder.getPutRequest(user, name);
    PutResponse response = service.put(request);
    return ResponseTypeFactory.getResponseType(response);
}

If there could be some delegate-like thing that would take a User and a String (as in the first line of each method), that would make that line abstractable to a generic method. However, note that the first line returns a different value (i.e., an instance of either Get or Put) and this value is used in the second line. The last line of each method is already the same, and uses polymorphism to figure out which version of getResponseType to call, so that's fine.

One difficulty is with the second line of each method where I need to call a different method. Perhaps I could have some interface that both Get and Put implement, then require a delegate-like thing that takes an instance of that interface. Then maybe both GetResponse and PutResponse could implement a different interface, and I could ensure there is a getResponseType that takes an instance of that interface.

Get and Put inherit from a common base class, Request. GetResponse and PutResponse inherit from a common base class, Response. I could probably make those base classes abstract and then, instead of having different interfaces, I could just have methods that take instances of the abstract base class necessary.

I'm not very familiar with Java, so I don't know the equivalent ways of doing things that I would do in C#. Thanks for the help.

Edit: here are my ideas for what interfaces might be necessary:

IRequest              IResponse
|     \                |     \
Get   Put       GetResponse  PutResponse

Then I would need these methods:

Builder.getRequest(User, String)
=> IRequest

service.getPut(IRequest)
=> IResponse

ResponseTypeFactory.getResponseType(IResponse)
=> State
+2  A: 

I don't think there is a good way in Java to improve on what you have. You could do something with interfaces but it would be more verbose. If your methods really are only 3 lines each I would stick with what you have. The code is clear and the duplication is minimal.

Dan Dyer
+1 having these two 3 lines seems well factored to me.
Adrian
+1  A: 

Java typically uses single method interfaces and anonymous inner classes for the equivalent of delegates but they would definitely be too verbose for the examples you've posted.

Your edit is the answer if you want to make your code a little more generic. You will need to change the Builder.getRequest method so that it takes in a parameter that indicates whether a Get or a Put is what you require (unless that can be deduced from either the 'user' or 'name' parameter).

On an unrelated and potentially controversial note, you may want to consider using Dependency Injection instead of static methods for Builder and ResponseTypeFactory.

jamie mccrindle
A: 

You can also consider to make use of an enum and a switch statement.

Basic example:

public enum RequestMethod { GET, PUT /* Add remaining here */ };

public State makeRequest(RequestMethod method, User user, String name) {
    Object response;
    switch (method) {
        case GET:
            response = service.get(Builder.getGetRequest(user, name));
            break;
        case PUT:
            response = service.put(Builder.getPutRequest(user, name));
            break;
        // Add remaining cases here.
    }
    return ResponseTypeFactory.getResponseType(response);
}
BalusC
A: 

I have implemented callback/delegate support in Java using reflection. Details and working source are available on my website. This would fit with what you are trying to do.

Software Monkey