Template Method
Template Method, a class behavioral pattern, provides the general steps of a method while deferring the implementation to its subclasses. Used to encapsulate algorithms, it can help reduce code duplication and maximizes the reuse of subclasses. Generally, an abstract base class is created, defining a template method of an algorithm. Later on, the subclasses can alter and implement the behavior.
UML Diagram
Code Examples
Java
//Coercion Polymorphism abstract class Add { public abstract double add(double d1, double d2);//template } class AddAnyTypeNumber extends Add{ public double add(double d1, double d2) { return d1 + d2; } } class Test { public static void main(String[] args) { double d1 = 10.5, d2 = 9.5; float f1 = 11.5f, f2 = 12.5f; long l1 = 1, l2 = 2; int i1 = 3, i2 = 4; short s1 = 7, s2 = 8; byte b1 = 5, b2 = 6; AddAnyTypeNumber addNumber = new AddAnyTypeNumber(); System.out.println(addNumber.add(d1,d2)); System.out.println((float)addNumber.add(f1,f2)); System.out.println((long)addNumber.add(l1,l2)); System.out.println((int)addNumber.add(i1,i2)); System.out.println((short)addNumber.add(s1,s2)); System.out.println((byte)addNumber.add(b1,b2)); } }
Source from Javacamp, http://www.javacamp.org/designPattern/template.html/
PHP 5.0
abstract class AbstractClass { public final function templateMethod() { print "AbstractClass::templateMethod() called.\n"; $this->mandatoryOperation(); $this->optionalOperation(); } protected abstract function mandatoryOperation(); protected function optionalOperation() { } } class ConcreteClass extends AbstractClass { protected function mandatoryOperation() { print "ConcreteClass::mandatoryOperation() called.\n"; } protected function optionalOperation() { print "ConcreteClass::optionalOperation() called.\n"; } }
Source from Zend Technologies, http://www.zend.com/zend/php5/php5-OOP.php?article=php5-OOP&kind=ph&id=3204&open=1&anc=0&view=1
Real-life Applications
Apache Excalibur
The following are portions of the code found in [CascadingErrorTestCase.java] and [CascadingEexceptionTestCase.java] files.
When comparing these two files, we can see that the two files share a common package org.apache.avalon.framework.test.
package org.apache.avalon.framework.test; import org.apache.avalon.framework.CascadingError; import org.apache.avalon.framework.CascadingThrowable; import junit.framework.TestCase;
From the following, we can see that the class CascadingErrorTestCase is extending from an abstract class called TestCase. This is the same case in the CascadingExceptionTestCase.java file. Hence, this shows that these two classes are subclasses of the class TestCase.
public class CascadingErrorTestCase extends TestCase { }
When looking at the testConstructor() in both files, we can see that it implements different methods, therefore its altering the algorithm operation of the file. Therefore we can conclude that the general steps in the constructor is not altered, but the implementation is different.
// From CascadingErrorTestCase.java public void testConstructor() { assertNotNull( new CascadingError( null, null ) ); assertNotNull( new CascadingError( "msg", null ) ); assertNotNull( new CascadingError( "msg", new RuntimeException() ) ); assertNotNull( new CascadingError( null, new RuntimeException() ) ); //assertNotNull( new CascadingError( "msg" ) ); //ambiguous assertNotNull( new CascadingError( null ) ); //assertNotNull( new CascadingError() ); }
// From CascadingExceptionTestCase.java public void testConstructor() { assertNotNull( new CascadingException( null, null ) ); assertNotNull( new CascadingException( "msg", null ) ); assertNotNull( new CascadingException( "msg", new RuntimeException() ) ); assertNotNull( new CascadingException( null, new RuntimeException() ) ); assertNotNull( new CascadingException( "msg" ) ); // ambiguous assertNotNull( new CascadingException( null ) ); //assertNotNull( new CascadingException() ); }
Source from | Apache Excalibur Test Framework via Google Code Search
Apache Tomcat
The following are portions of the code found in [Shm.java] and
[Shm14.java]
Looking at the Shm14.java, we can conclude that Shm.java is the base class while 'Shm14.java' is the subclass. As you can see, Shm also extends to JniHandler, making it a subclass of that class.
// From Shm14.java public class Shm14 extends Shm { }
// From Shm.java public class Shm extends JniHandler { }
From the file Shm.java, the following method is given.
public void resetScoreboard() throws IOException { if( apr==null ) return; MsgContext mCtx=createMsgContext(); Msg msg=(Msg)mCtx.getMsg(0); msg.reset(); msg.appendByte( SHM_RESET ); this.invoke( msg, mCtx ); }
In the 'Shm14.java' file, the method from the base class is overridden with the following new one. Its implementation is different.
public void resetScoreboard() throws IOException { // XXX Need to write the head }
References
Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. ISBN 0-201-63361-2.
Template Method on Wikipedia
BTP600 Wiki Page