O que é Template Method?
Desenvolvimento
OO atual consiste na criação de sistema complexos onde o simples
polimorfismo não resolve com coerência os problemas encontrados. Por
isso existem os Design Patterns (padrões de projeto) que consistem em
apresentar várias técnicas de desenvolvimento para determinados
problemas. Template Method é um desses padrões. Vide mais informações
sobre GoF em:
http://en.wikipedia.org/wiki/Design_Patterns
Onde utilizar um Template Method?
Imagine
a seguinte situação: precisamos definir um esqueleto de algorítimo que
não pode ser modificado, porém que é constituido de etapas nas quais
devem variar de caso a caso. Este problema é resolvido por um template
method. Veja o código, sem o template method, abaixo:
interface IMyExample {
public void operationOne();
public void operationTwo();
public int calculate();
}
class MyExample implements IMyExample {
protected int number;
public MyExample() { number = 0; }
@Override
public void operationOne() { number++; }
@Override
public void operationTwo() { number--; }
@Override
public int calculate() {
operationOne();
operationTwo();
return number;
}
}
class ExampleA extends MyExample {
@Override
public void operationOne() {
number += 2;
}
}
class ExampleB extends MyExample {
@Override
public void operationTwo() {
number -= 2;
}
}
class TestDriver {
public static void main(String args[]) {
ExampleA a = new ExampleA();
ExampleB b = new ExampleB();
System.out.println( "A: " + a.calculate() );
System.out.println( "B: " + b.calculate() );
}
}
Este é um caso típico de objetos polimórficos onde cada um se comporta da maneira esperada. Onde este exemplo apresenta falhas?
-
Nossa assinatura é definida por uma interface e por consequência, os métodos são públicos. Porém, em nosso projeto, os métodos operationOne() e operationTwo() definem comportamentos que não poderiam ser acessados externamente. O encapsulamento fica prejudicado.
-
Nosso método calculate() também poderia ser sobrescrito. Isso poderia ser facilmente resolvido, mas o design pattern também vai garantir esse comportamento.
Resolvendo o mesmo problema com Template Method
Vamos
agora ao mesmo problema com a aplicação do padrão. Suponha que o método
operationOne() deve ser obrigatoriamente sobrescrito. Já o método
operationTwo() pode ser sobrescrito, mas opcionalmente.
abstract class MyExample {
protected int number;
public MyExample() { number = 0; }
// Método que precisa ser sobrescrito
protected abstract void doOperationOne();
// Método que pode ser sobrescrito
protected void operationTwoHook() { number--; }
// Template Method
public final int calculate() {
doOperationOne();
operationTwoHook();
return number;
}
}
class ExampleA extends MyExample {
@Override
protected void doOperationOne() {
number++;
}
}
class ExampleB extends MyExample {
@Override
protected void doOperationOne() {
number += 2;
}
@Override
protected void operationTwoHook() {
number--;
}
}
class TestDriver {
public static void main(String args[]) {
ExampleA a = new ExampleA();
ExampleB b = new ExampleB();
System.out.println( "A: " + a.calculate() );
System.out.println( "B: " + b.calculate() );
}
}
Algumas vantagens são encontradas neste padrão:
-
Observe que doOperationOne() é abtract e portanto existe a necessidade de sobrescrever
-
A notação do no início do método é uma forma de representar que o método precisa ser sobrescrito (use esta notação se quiser!)
-
O método operationTwoHook() já possui um comportamento padrão, porém, pode ou não ser sobrescrito
-
A notação Hook no final do método indica que a sobrescrição do mesmo é opcional
-
O encapsulamento foi garantido, pois ambos os métodos são protected
-
O método validate() é nosso template method, ou seja, o esqueleto do algoritmo que em hipótese nenhuma pode ser modificado. Por isso ele é final
Esse
foi um simples exemplo que compreende o padrão template method. Existem
vários casos onde o mesmo poderá ser aplicado. Uma situação de login de
usuário no sistema, por exemplo. O ato de login é sempre o mesmo, porem
algumas de suas etapas podem variar de sistema para sistema. Você
poderá construir uma biblioteca genérica de login trabalhando com esse
padrão.
"Não acordo entre Homens e Leões" Aquiles
Bons estudos!
Guilherme Pontes
Nenhum comentário:
Postar um comentário