1

So I have the following structure:

public abstract class Processor<T extends BaseContainer> {
    protected abstract T initializeContainer(String requestID, Map<String, String> details);

    protected abstract boolean validateContainer(T request);
    protected abstract void process(T request);

    public final process(String requestID, Map<String, String> details) {
        T request = initializeContainer(requestID, details);
        if (!validateContainer(request)) {
            process(request);
        }
    }
}

public abstract class BaseContainer() {
    protected final String requestID;
    protected BaseContainer(String requestID, Map<String, String> details) {
        this.requestID = requestID;
        // set some other fields using details
    }
}

Everytime I need to add a new Processor (with a corresponding new Container), I will need to:

public class SampleProcessor extends Processor<SampleContainer> {
    @Override
    protected SampleContainer initializeContainer(String requestID, Map<String, String> details) {
        return new SampleContainer(requestID, details);
    }
}

// SampleContainer can contain other details, but omitted for clarity
public class SampleContainer extends BaseContainer {
    public SampleContainer(String requestID, Map<String, String> details) {
        super(requestID, details);
    }
}

I don't like the fact that I need to override initializeContainer for every Processor I add, especially when I don't change the constructor's parameters of Container (it will be always String requestID, Map<String, String> details

I understand that I can't simple call new T(requestID, details) in Processor. And I would imagine I will need some sort of factory (?) if I want to implement initializeContainer at base class.

Can you help to suggest anyway I can achieve this? Thank you.


Edit 1: I added two more methods to provide better context Processor

2
  • What is the purupose of BaseContainer?. As it stands, it doesn't seem to do much and you could do away with it. Commented Jan 21, 2017 at 7:38
  • @CKing It contains the details of the input request to be process by the Processor Commented Jan 21, 2017 at 7:41

2 Answers 2

1

Everythings fine

This is a pattern called the abstract-factory.

Everytime I need to add a new Processor (with a corresponding new Container), I will need to:

This is the main intend of the pattern (ebenda)

the client (you) software creates a concrete implementation (your SampleProcessor) of the abstract factory (Processor) and then uses the generic interface of the factory to create (via initializeContainer) the concrete objects (your SampleContainer)...

Sign up to request clarification or add additional context in comments.

2 Comments

Good to know. Thanks for the answer
@harry at your service ;)
0

I'd refactor the method name to createContainer, because that's what you do with your implementation - you don't setup an existing one but the make a new one.

Your simple example only calls the container constructor. But the 'processor creation and initialization' process could vary. Maybe, some processors for some container need special treatment. Then the implementations of the method would look different for each container subclass again.

An alternative common pattern, to solve this common problem, would be adding another abstract method like

public abstract Class<T> getProcessorType();

and implement it like this on every container implementation:

@Override
public Class<MyProcessor> getProcessorType() {
    return MyProcessor.class;
}

The base class then could implement the create method for processors:

public T createProcessor(String requestID, Map<String, String> details) {
    T processor;
    try {
        processor = getProcessorType().newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
        e.printStackTrace();  // or handle correctly
    }
    processor.init(requestId, details)
    return processor;
}

(Note that this requires a no-args processor constructor)

3 Comments

Thanks @Andreas_D for your suggesting. I have added two more methods in Processor to provide better context. So no, Processor is not tied to requestID and details map
There's no call for using reflection there.
@TomHawtin-tackline - That's why I called it 'alternative common pattern'. Should I put it in bold?

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.