Search code examples
design-patternsrefactoring

How to refactor this template method implemetation


I have a bastard template method implementation. Rather than being a base class with subclass implementations, it is a static method on a util class that takes an interface to which it delegates. I want to refactor this to the more common pattern so I can stop passing the Domain class around.

The first step I think is turn template into an object method, but then I am at a loss for inspiration as to how to move my 5 Helper implementations (not shown) into subclasses of the new Template object.

public interface Helper
{
    void doFirstThing(Domain d);
    void doSecondThing(String id);
}

public class UtilClass
{
    public static void  template(Domain d,  Helper h, String who)
    {
        //begin database transaction
        try
        {
            //some logic
            h.doFirstThing(d);
            //more computation

            h.doSecondThing(d.getId());
            //database commit();
        }
        finally
        {
            //if transaction open database rollback();
        }
    }
}

public class Domain
{

    public String getId()
    {
        return "value";
    }

}

Solution

  • I thought about it some more and came up with the following steps.

    1. Replace Method with Method Object. Leave the helper out of the constructor arguments. I also skip the part about making local variables fields. The automated refactorings do that so well when I want it done.

    2. Inline the static method.

    3. Make an implementation a subclass of the new MethodObject. this involves adding/modifying a/the constructor.

    4. Where the Method Object is created and called with the implementation, just create the implementation and call the template method.

      new MethodObject(d, who).template(new Implementation(d, who));
      

    becomes

        Implementation impl = new Implementation(d, who);
        impl.template(impl);
    
    1. Repeat steps 3 and 4 for the other implementations.
    2. Make the MethodObject/Baseclass abstract and add the methods from the interface as abstract methods.
    3. Update the MethodObject/Baseclass to use the abstract methods.
    4. Remove the Helper interface as a parameter now that it isn't being used.
    5. Remove the interface declaration from the subclasses.
    6. Delete the Helper Interface.
    7. Parameters to the methods previously defined on the interface that are fields on the parent class can be removed. This can be extended to values gotten from fields. Since d is a field, d.getId() doesn't need to be passed. doSecondThing(d.getId());