Difference between revisions of "Template Method"

From CDOT Wiki
Jump to: navigation, search
(Real-life Application)
(Apache)
Line 76: Line 76:
 
== Real-life Application ==
 
== Real-life Application ==
  
=== Apache ===
+
=== Apache Excalibur===
 +
 
 +
 
 
<pre>
 
<pre>
/*
+
/*  
  * Copyright 1997-2004 The Apache Software Foundation
+
  * Licensed to the Apache Software Foundation (ASF) under one or more
  *
+
* contributor license agreements.  See the NOTICE file distributed with
  * Licensed under the Apache License, Version 2.0 (the "License");
+
  * this work for additional information regarding copyright ownership.
* you may not use this file except in compliance with the License.
+
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * You may obtain a copy of the License at
+
* (the "License"); you may not use this file except in compliance with
  *
+
* the License.  You may obtain a copy of the License at
  *     http://www.apache.org/licenses/LICENSE-2.0
+
  *  
  *
+
  *   http://www.apache.org/licenses/LICENSE-2.0
 +
  *  
 
  * Unless required by applicable law or agreed to in writing, software
 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
+
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 +
* implied.
 +
*
 
  * See the License for the specific language governing permissions and
 
  * See the License for the specific language governing permissions and
 
  * limitations under the License.
 
  * limitations under the License.
 
  */
 
  */
package org.apache.avalon.framework.component.test;
+
 
 +
package org.apache.avalon.framework.test;
 +
 
 +
import org.apache.avalon.framework.CascadingError;
 +
import org.apache.avalon.framework.CascadingThrowable;
  
 
import junit.framework.TestCase;
 
import junit.framework.TestCase;
import org.apache.avalon.framework.component.Component;
 
import org.apache.avalon.framework.component.ComponentException;
 
import org.apache.avalon.framework.component.DefaultComponentManager;
 
  
 
/**
 
/**
  * Test the basic public methods of DefaultComponentManager.
+
  * TestCase for {@link CascadingError}.
 
  *
 
  *
 
  * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
 
  * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
 +
* @version $Id$
 
  */
 
  */
public final class DefaultComponentManagerTestCase
+
public class CascadingErrorTestCase extends TestCase
    extends TestCase
 
 
{
 
{
 +
    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() );
 +
    }
  
     class DefaultRoleA
+
     public void testGetCause()
        implements Component,RoleA
 
 
     {
 
     {
         public DefaultRoleA()
+
         RuntimeException re = new RuntimeException();
 +
        CascadingError e = new CascadingError( "msg", re );
 +
 
 +
        assertEquals( re, e.getCause() );
 +
 
 +
        e = new CascadingError( "msg", null );
 +
        assertNull( e.getCause() );
 +
 
 +
        // default to jdk 1.3 cause (not that it seems to help,
 +
        // but it still makes sense)
 +
        /*Exception exc = new Exception("blah");
 +
        try
 
         {
 
         {
 +
            try
 +
            {
 +
                throw exc;
 +
            }
 +
            catch( Exception ex )
 +
            {
 +
                throw new CascadingError();
 +
            }
 
         }
 
         }
 +
        catch( CascadingError ex )
 +
        {
 +
            ex.getCause();
 +
        }*/
 
     }
 
     }
  
     class DefaultRoleB
+
     public void testCasts()
        implements Component,RoleB
 
 
     {
 
     {
         public DefaultRoleB()
+
         CascadingError e = new CascadingError( "msg", null );
         {
+
         assertTrue( e instanceof Error );
         }
+
         assertTrue( e instanceof CascadingThrowable );
 
     }
 
     }
  
 +
}
 +
</pre>
 +
<pre>
 +
/*
 +
* Licensed to the Apache Software Foundation (ASF) under one or more
 +
* contributor license agreements.  See the NOTICE file distributed with
 +
* this work for additional information regarding copyright ownership.
 +
* The ASF licenses this file to You under the Apache License, Version 2.0
 +
* (the "License"); you may not use this file except in compliance with
 +
* the License.  You may obtain a copy of the License at
 +
*
 +
*  http://www.apache.org/licenses/LICENSE-2.0
 +
*
 +
* Unless required by applicable law or agreed to in writing, software
 +
* distributed  under the  License is distributed on an "AS IS" BASIS,
 +
* WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 +
* implied.
 +
*
 +
* See the License for the specific language governing permissions and
 +
* limitations under the License.
 +
*/
  
    private DefaultComponentManager m_componentManager;
+
package org.apache.avalon.framework.test;
  
    protected boolean m_exceptionThrown;
+
import org.apache.avalon.framework.CascadingException;
 +
import org.apache.avalon.framework.CascadingThrowable;
  
 +
import junit.framework.TestCase;
  
    public DefaultComponentManagerTestCase()
+
/**
    {
+
* TestCase for {@link CascadingException}.
        this("DefaultComponentManager Test Case");
+
*
    }
+
* @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
 
+
* @version $Id$
     public DefaultComponentManagerTestCase( final String name )
+
*/
 +
public class CascadingExceptionTestCase extends TestCase
 +
{
 +
     public void testConstructor()
 
     {
 
     {
         super( name );
+
         assertNotNull( new CascadingException( null, null ) );
    }
+
        assertNotNull( new CascadingException( "msg", null ) );
 +
        assertNotNull(
 +
                new CascadingException( "msg", new RuntimeException() ) );
 +
        assertNotNull( new CascadingException( null, new RuntimeException() ) );
  
    protected void setUp()
+
        assertNotNull( new CascadingException( "msg" ) );
         throws Exception
+
         // ambiguous assertNotNull( new CascadingException( null ) );
    {
+
         //assertNotNull( new CascadingException() );
        m_componentManager = new DefaultComponentManager();
 
         m_exceptionThrown = false;
 
 
     }
 
     }
  
     protected  void tearDown()
+
     public void testGetCause()
        throws Exception
 
 
     {
 
     {
         m_componentManager = null;
+
         RuntimeException re = new RuntimeException();
    }
+
        CascadingException e = new CascadingException( "msg", re );
 
 
    /**
 
    * lookup contract:
 
    * return first component found for role
 
    * search in hirarchy from current componentManager up.
 
    * if no compnent exist for role a in hierarchy
 
    * throw ComponentException
 
    */
 
  
 +
        assertEquals( re, e.getCause() );
  
    public void testlookup1()
+
         e = new CascadingException( "msg", null );
        throws Exception
+
         assertNull( e.getCause() );
    {
 
         DefaultRoleB roleBinBase = new DefaultRoleB();
 
        DefaultRoleB roleBinParent = new DefaultRoleB();
 
        DefaultRoleA roleAinParent = new DefaultRoleA();
 
 
 
        m_componentManager.put(RoleA.ROLE,roleAinParent);
 
         m_componentManager.put(RoleB.ROLE,roleBinParent);
 
        DefaultComponentManager baseComponentManager = new DefaultComponentManager(m_componentManager);
 
        baseComponentManager.put(RoleB.ROLE,roleBinBase);
 
        Object lookupAinBase = baseComponentManager.lookup(RoleA.ROLE);
 
        Object lookupBinBase = baseComponentManager.lookup(RoleB.ROLE);
 
        Object lookupBinParent = m_componentManager.lookup(RoleB.ROLE);
 
        assertTrue( lookupAinBase instanceof RoleA);
 
        assertEquals( lookupBinBase, roleBinBase );
 
        assertEquals( lookupBinParent, roleBinParent );
 
        assertEquals( lookupAinBase,roleAinParent);
 
    }
 
  
    public void testlookup2()
+
        // default to jdk 1.3 cause (not that it seems to help,
         throws Exception
+
        // but it still makes sense)
    {
+
         /*Exception exc = new Exception("blah");
        m_componentManager.put(RoleA.ROLE,new DefaultRoleA());
 
        Object o = null;
 
 
         try
 
         try
 
         {
 
         {
             o = m_componentManager.lookup(RoleB.ROLE);
+
             try
 +
            {
 +
                throw exc;
 +
            }
 +
            catch( Exception ex )
 +
            {
 +
                throw new CascadingException();
 +
            }
 
         }
 
         }
         catch       (ComponentException ce)
+
         catch( CascadingException ex )
 
         {
 
         {
             m_exceptionThrown = true;
+
             ex.getCause();
        }
+
         }*/
        if (o == null)
 
            assertTrue("ComponentException was not thrown when component was not found by lookup." ,m_exceptionThrown );
 
         else
 
            assertTrue("component was found by lookup ,when there was no component.",false);
 
 
 
    }
 
 
 
    public void testhasComponent()
 
        throws Exception
 
    {
 
        m_componentManager.put(RoleA.ROLE,new DefaultRoleA());
 
        assertTrue(m_componentManager.hasComponent(RoleA.ROLE));
 
        assertTrue(!m_componentManager.hasComponent(RoleB.ROLE));
 
 
     }
 
     }
  
     public void testmakeReadOnly()
+
     public void testCasts()
        throws Exception
 
 
     {
 
     {
         //before read only
+
         CascadingException e = new CascadingException( "msg", null );
        m_componentManager.put(RoleA.ROLE,new DefaultRoleA());
+
         assertTrue( e instanceof Exception );
        Object a = m_componentManager.lookup(RoleA.ROLE);
+
         assertTrue( e instanceof CascadingThrowable );
         assertTrue( a instanceof RoleA);
 
        m_componentManager.makeReadOnly();
 
        //after read only
 
        try
 
        {
 
            m_componentManager.put(RoleB.ROLE,new DefaultRoleB());
 
        }
 
        catch        (IllegalStateException se)
 
        {
 
            m_exceptionThrown = true;
 
        }
 
         assertTrue("IllegalStateException was not thrown in  put after makeReadOnly." , m_exceptionThrown );
 
 
     }
 
     }
 
}
 
}

Revision as of 18:21, 19 March 2007

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

TemplateMethod.JPG

Source from GoF's Design Patterns - Elements of Reusable Object -Oriented Software (pg. 325)

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 Application

Apache Excalibur

/* 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed  under the  License is distributed on an "AS IS" BASIS,
 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 * implied.
 * 
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.avalon.framework.test;

import org.apache.avalon.framework.CascadingError;
import org.apache.avalon.framework.CascadingThrowable;

import junit.framework.TestCase;

/**
 * TestCase for {@link CascadingError}.
 *
 * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
 * @version $Id$
 */
public class CascadingErrorTestCase extends TestCase
{
    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() );
    }

    public void testGetCause()
    {
        RuntimeException re = new RuntimeException();
        CascadingError e = new CascadingError( "msg", re );

        assertEquals( re, e.getCause() );

        e = new CascadingError( "msg", null );
        assertNull( e.getCause() );

        // default to jdk 1.3 cause (not that it seems to help,
        // but it still makes sense)
        /*Exception exc = new Exception("blah");
        try
        {
            try
            {
                throw exc;
            }
            catch( Exception ex )
            {
                throw new CascadingError();
            }
        }
        catch( CascadingError ex )
        {
            ex.getCause();
        }*/
    }

    public void testCasts()
    {
        CascadingError e = new CascadingError( "msg", null );
        assertTrue( e instanceof Error );
        assertTrue( e instanceof CascadingThrowable );
    }

}
/* 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed  under the  License is distributed on an "AS IS" BASIS,
 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 * implied.
 * 
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.avalon.framework.test;

import org.apache.avalon.framework.CascadingException;
import org.apache.avalon.framework.CascadingThrowable;

import junit.framework.TestCase;

/**
 * TestCase for {@link CascadingException}.
 *
 * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
 * @version $Id$
 */
public class CascadingExceptionTestCase extends TestCase
{
    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() );
    }

    public void testGetCause()
    {
        RuntimeException re = new RuntimeException();
        CascadingException e = new CascadingException( "msg", re );

        assertEquals( re, e.getCause() );

        e = new CascadingException( "msg", null );
        assertNull( e.getCause() );

        // default to jdk 1.3 cause (not that it seems to help,
        // but it still makes sense)
        /*Exception exc = new Exception("blah");
        try
        {
            try
            {
                throw exc;
            }
            catch( Exception ex )
            {
                throw new CascadingException();
            }
        }
        catch( CascadingException ex )
        {
            ex.getCause();
        }*/
    }

    public void testCasts()
    {
        CascadingException e = new CascadingException( "msg", null );
        assertTrue( e instanceof Exception );
        assertTrue( e instanceof CascadingThrowable );
    }
}

References

BTP600 Wiki Page
Template Method on Wikipedia