Este sencillo patrón resulta útil en casos en los que podamos implementar en una clase abstracta el código común que será usado por las clases que heredan de ella, permitiéndoles que implementen el comportamiento que varía mediante la reescritura (total o parcial) de determinados métodos.
La diferencia con la forma común herencia y sobreescritura de los métodos abstractos estriba en que la clase abstracta contiene un método denominado 'plantilla' que hace llamadas a los que han de ser implementados por las clases que hereden de ella.
A continuación veremos un ejemplo en el que utilizamos este patrón de diseño.
Main.java:
package TemplateMethod01;
public class Main
{
public static void main(String[] args)
{
ClaseConcreta1 cc1 = new ClaseConcreta1();
ClaseConcreta2 cc2 = new ClaseConcreta2();
// Obtener el resultado de multiplicar 3 por 100 y restarle 10
int num1 = cc1.obtener(3);
System.out.println( "num1: " + num1 );
// Obtener el resultado de multiplicar 3 por 1000 y restarle 100
int num2 = cc2.obtener(50);
System.out.println( "num2: " + num2 );
}
}
ClaseAbstracta.java:
package TemplateMethod01;
public abstract class ClaseAbstracta
{
public int obtener( int num )
{
this.mensaje();
int numero = this.multiplicar( num );
numero = this.sumar( numero );
return numero;
}
// -------------------
public void mensaje()
{
System.out.println("Vamos a realizar las operaciones...");
}
// -------------------
// Métodos que deberán implementar las subclases
public abstract int multiplicar( int num );
public abstract int sumar( int num );
}
ClaseConcreta1.java:
package TemplateMethod01;
public class ClaseConcreta1 extends ClaseAbstracta
{
public ClaseConcreta1(){
}
// ------------------------------------
@Override
public int multiplicar( int num )
{
return num * 100;
}
// ------------------------------------
@Override
public int sumar( int num )
{
return num + 10;
}
}
ClaseConcreta2.java:
package TemplateMethod01;
public class ClaseConcreta2 extends ClaseAbstracta
{
public ClaseConcreta2(){
}
// ------------------------------------
@Override
public int multiplicar( int num )
{
return num * 1000;
}
// ------------------------------------
@Override
public int sumar( int num )
{
return num + 100;
}
}
Al ejecutarlo obtendríamos como resultado:
EXPLICACIÓN:
- En ClaseAbstracta se define el método plantilla obtener(), desde el que se llama a dos métodos definidos como abstractos (que serán implementados por las subclases).
- En ClaseConcreta1 se implementan dichos métodos de forma que uno de ellos devuelve el número entero recibido como parámetro multiplicado por 100, y otro agregándole 10.
- En ClaseConcreta2 se implementan de modo que lo devuelven multiplicado por 1000 y agregándole 100, respectivamente.
En ciertos casos será necesario que algunas subclases sobreescriban determinados métodos de la clase padre para agregar determinadas funcionalidades.
Por ejemplo, si queremos que ClaseConcreta2 sobreescriba el método mensaje() con el fin de que se muestre otro texto antes del ya definido en dicho método lo haríamos del siguiente modo:
ClaseConcreta2.java:
package TemplateMethod02;
public class ClaseConcreta2 extends ClaseAbstracta
{
public ClaseConcreta2(){
}
// ------------------------------------
@Override
public void mensaje()
{
// Procesamos código extra
System.out.println("En ClaseConcreta2");
// Llamamos al código del método implementado en la clase abstracta
super.mensaje();
}
// ------------------------------------
@Override
public int multiplicar( int num )
{
return num * 1000;
}
// ------------------------------------
@Override
public int sumar( int num )
{
return num + 100;
}
}