Home | FAQ | Contact me

The Template pattern in Java...


...including observations on problems of polymorphism. It's useful to walk through this code in the debugger or compare the print statements with the output. However, it's not really so much about the template pattern, but more about shallow, polymorphic behavior.

What led me to do this experiment was brownfield work, modifying without profoundly transforming an existing superclass (here, Parent) so that modifications of numerous subclasses (here, Child) would not be forced on me because yielding to the temptation of creating new, abstract methods in the superclass: I would be able to modify just the subclasses I wanted without having to commit scores of subclasses immediately (or even long-term).

Parent.java:
public abstract class Parent
{
  protected String id;
  protected String version;

  protected String getId()                      { return id; }
  protected String getVersion()                 { return version; }
  protected void   setId( String id )           { this.id      = id; }
  protected void   setVersion( String version ) { this.version = version; }

  public void doStuff()
  {
    System.out.println( "    doStuff() called in Parent!" );
    System.out.println( "           getId() = " + getId() );
    System.out.println( "      getVersion() = " + getVersion() );
  }

  public void doOtherStuff()
  {
    System.out.println( "    doOtherStuff() called in Parent!" );
    System.out.println( "           getId() = " + getId() );
    System.out.println( "      getVersion() = " + getVersion() );
  }
}
Child.java:
public class Child extends Parent
{
  protected String getId()      { return "Child's " + id; }
  protected String getVersion() { return "Child's " + version; }

  public void doStuff()
  {
    System.out.println( "    doStuff() called in Child!" );
    System.out.println( "           getId() = " + getId() );
    System.out.println( "      getVersion() = " + getVersion() );
    System.out.println( "    Call super.doStuff()..." );
    super.doStuff();
  }
}

Output



Call main()...
  setId( "asdf" )...
  setVersion( "2" )...

  Call doStuff(), but, which doStuff()?
    doStuff() called in Child!
           getId() = Child's asdf
      getVersion() = Child's 2
    Call super.doStuff()...
    doStuff() called in Parent!
           getId() = Child's asdf
      getVersion() = Child's 2

  Call doOtherStuff()...
    doOtherStuff() called in Parent!
           getId() = Child's asdf
      getVersion() = Child's 2
 
Test.java:
public class Test
{
  public static void main( String[] args )
  {
    Parent object = new Child();

    System.out.println( "Call main()..." );
    System.out.println( "  setId()..." );
    System.out.println( "  setVersion()..." );
    object.setId( "asdf" );
    object.setVersion( "2" );

    System.out.println( "\n    Call doStuff(), but, which doStuff()?" );
    object.doStuff();
    System.out.println( "\n    Call doOtherStuff()..." );
    object.doOtherStuff();
  }
}

Observations