0

I have a class that represents a vendor service and all their services have an authentication and an execute method.

I started thiking of an abstract class that represents this as below. The thing is each of their services require a different request object, so I thought of using generics. The problem is that if use it, I can't handle the specifics of each request object. Each children must use some methods from the type.

1) Should I try to make this way I'm trying, or remove this executeRequest method from the abstract class and each subclass implement it with the correct type?

2) I always hear "prefer composition over inheritance". Should I move the executeRequest to an interface?

Thanks in advance!

public abstract class VendorService  {

    private final VendorInitialization VendorInitialization;

    //a bean with some auth params
    public VendorService(VendorInitialization VendorInitialization) {
        this.VendorInitialization = VendorInitialization;
    }

    protected abstract <T> boolean validateRequest(T requestObject) throws VendorServiceBadRequest;

    protected abstract <T, P> P executeRequest(T requestObject);
}


public class VendorServiceAllocation extends VendorService {

    public VendorServiceAllocation(VendorInitialization VendorInitialization) {
        super(VendorInitialization);
    }

    @Override
    protected <T> boolean validateRequest(T requestObject) throws VendorServiceBadRequest {

        //List<BeanAllocation> requestObject = new Arraylist<>(); //I was using like this before

        //TODO: how to handle it as list of on this specific case?
        if (requestObject == null || requestObject.size() == 0) {
            throw new VendorServiceBadRequest(String.format("The list must have at least one element"));
        }

        //TODO: requestObject.get(0).getMySpecificFieldFromBeanAllocation will not work

        //some checks
        return true;
    }

    @Override
    protected <T, P> P executeRequest(T requestObject) {
        //executes and return a list of objects specific to this class
        return new List<BeanAllocationResponse>();
    }
}

Edit, for clarification: In the child class VendorServiceAllocation, I need to use some methods that are specific of that type.

E.g.: Inside executeRequest, I need to call requestObject.customFunctionFromChild()

5
  • 1
    I think your abstract implementation is just fine; you just need to make sure that the functionality you abstract to the generic parent is useful for all of the children. Commented Jul 18, 2016 at 17:15
  • Thinking as a executeRequest, all children will use it. But if I think of the objects, each children will receive a different object. I should remove it from the abstract then? Or do you think I could use generics, something? Commented Jul 18, 2016 at 17:20
  • 3
    you're making the abstract methods generic while the class is not, instead make the class generic , then you could have sub-class Service1 that inherits Parent<Integer> and another that inherits Parent<String>(Integer and String are just examples for illustration ) Commented Jul 18, 2016 at 17:26
  • oh nice!! this is what I was looking! the way you suggested, each children will know its type and I can work it.. please comment it as answer so I can mark it correct.. :) Commented Jul 18, 2016 at 17:33
  • It's not immediately clear if you need type parameters. I think just working with types as interfaces (e.g. make a Request class that validateRequest accepts) Commented Jul 18, 2016 at 17:38

1 Answer 1

3

I think niceman hit the nail on the head, though I am not quite sure what you are asking. eg.

abstract class Service<T,P>{
    abstract public P processRequest(T t);
}

Then you can implement it in one of two ways.

class StringService extends Service<String, String>{
    public String processRequest(String t){
         return t;
    }
}

Or you could leave it to still be Generic and the actual instances would have the different types.

class OtherService<T> extends Service<T, String>{
    public String processRequest(T t){
        return t.toString();
    }
}

Where you could use it as,

OtherService<Integer> is = new OtherService<>();
Sign up to request clarification or add additional context in comments.

1 Comment

this is exactly what I wanted.. I upvoted your answer, but I asked for @niceman to post his reply as an answer as he replied first.. hope you understand! :)

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.