Search code examples
javastatelesstemplate-method-pattern

Stateless Template method implementation


Let's say I have a Strategy interface :

public interface Strategy {

    void perform();

}

And a template method to implement it :

public abstract class AbstractStrategy implements Strategy {

    @Override
    public void perform() {
        String firstInfo = doStuff();
        String secondInfo = firstDelegationToImplementor(firstInfo);
        String thirdInfo = processSecondInfo(secondInfo);
        String fourthInfo = secondDelegationToImplementor(thirdInfo);
        finalProcessing(fourthInfo);
    }

    private void finalProcessing(String fourthInfo) {
        //TODO automatically generated method body, provide implementation.

    }

    protected abstract String secondDelegationToImplementor(String thirdInfo);

    protected abstract String firstDelegationToImplementor(String firstInfo);

    private String processSecondInfo(String secondInfo) {
        return "thirdResult";
    }

    private String doStuff() {
        return "firstResult";
    }
}

And I have a concrete subclass of that :

public class ConcreteStrategy extends AbstractStrategy {

    private String firstInfo;

    @Override
    protected String secondDelegationToImplementor(String thirdInfo) {
        return someMoreProcessing(firstInfo, thirdInfo);
    }

    private String someMoreProcessing(String firstInfo, String thirdInfo) {
        return null;
    }

    private String someProcessing(String firstInfo) {
        return null;
    }

    @Override
    protected String firstDelegationToImplementor(String firstInfo) {
        this.firstInfo = firstInfo;
        return someProcessing(firstInfo);
    }
}

But due to the fact that it needs to remember some intermediate result in between the method calls it is not stateless. Stateless classes have several advantages, they are automatically thread safe for instance.

So the question is : how can I make ConcreteStrategy stateless, while taking advantage of the template method?

(edit) Clarification : the published methods of both the interface and the template method class cannot change.

(note, I have solved this question already and will answer it myself, but I'll give others a chance to solve it)


Solution

  • Ok here's the answer I have come up with when I faced this :

    public class StatelessConcreteStrategy implements Strategy {
    
        @Override
        public void perform() {
            new ConcreteStrategy().perform();
        }
    }
    

    StatelessConcreteStrategy is stateless. It has all the benefits any other stateless class has, and by delegating the perform() to a new ConcreteStrategy instance, it gets to use the template method pattern, and is able to 'remember' any data it wants to in between method calls.

    In fact you'll most likely want to inline ConcreteStrategy to an inner or even anonymous inner class.