Padrões de Projeto - Template Method (pt-BR)
O Template Method é um Padrão de Projeto muito utilizado, bem provável que você já o implementou talvez sem se quer saber, ou que você futuramente o implementará, esse padrão possui uma abstração simples de assimilação o que torna o mesmo mais popular a grande comunidade de desenvolvedores , diferente de outros padrões de nível complexo.
Qual é a proposta do Template Method?
O Template Method tem como proposta facilitar a implementação de cenários onde se deseja encapsular algoritmos, fornecendo as classes derivadas o poder de definir as pré-condições (input) do algoritmo e deixando a classe Base responsável pela estrutura do algoritmo, pré-condições globais que fazem sentido a todas classes deviradas, bem como, as pós-condições (output).
A idéia básica por trás desse modelo é disponibilizar uma única classe base que ficará responsável pela estrutura do algoritmo, evitando ter "pedaços" do algoritmo espalhados pelas classes deviradas o que gera redundância no código, a classe derivada será responsável de implementar o algoritmo de forma independente, cada classe devirada implementará o algoritmo de uma forma diferente ou igual porém sempre respeitando a estrutura do algoritmo que estará definida na classe Base.
Diagrama de classe de um Template Method
Interessante observar que existe uma classe abstrata que será herdada pelas demais classes, sendo que dentro dessa classe abstrata nós temos um templateMethod() no corpo do templateMethod temos outros dois métodos que serão implementados pelas classes deviradas.
Contextualizando com a realidade
Como o objetivo principal desse padrão é encapsular algoritmo, nada melhor que definir um processo.
Existe uma Empresa em São Paulo chamada "Docearia DevBrasil" sua especialidade é fazer bolos, porém devida a desorganização os bolos estão saindo diferentes, ou seja, você compra um bolo de chocolate hoje o sabor é x e se você comprar amanhã o mesmo bolo o sabor é y, isso acontece porque dentro da docearia existem 2 funcionários (Padeiro e Confeiteiro) que fazem bolos de chocolate e cada um faz de uma forma.
O Departamento de Marketing constatou o problema e para evitar o declínio do negócio pediu uma automação desse processo com extrema urgencia ao Departamento de TI.
Depois de uma longa conversa a equipe de TI, resolveu mudar o processo que obrigou o Padeiro, Confeiteiro ou qualquer outro funcionário (Classe Derivada) da docearia a seguir um modelo de fazer bolo(template method) estabelecido por uma cartilha (Classe Base) para fazer um bolo.
Observando esse processo pela ótica OO
**
No código que segue abaixo é interessante observar que o padeiro e o confeiteiro não sabem como se faz um bolo eles apenas dizem eu quero o bolo de chocolate ou de morango e a classe Bolo fará todo o trabalho que já esta estruturado dentro da classe BoloBase que é herdada pela classe Bolo.
using System;
namespace DevBrasil
{
public class EBolo
{
public enum TipoBolo { Chocolate = 1, Morango = 2}
}
}
using System;
namespace DevBrasil
{
public abstract class BoloBase
{
// template method
public void FazerBolo
{
Passo1();
Passo2();
}
}
// esqueleto dos métodos
public abstract void Passo1();
public abstract void Passo2();
}
using System;
namespace DevBrasil
{
public class Bolo : BoloBase
{
private EBolo.TipoBolo tipoBolo;
public Bolo(EBolo.TipoBolo _tipoBolo)
{
tipoBolo = _tipoBolo;
}
public override void Passo1()
{
if(EBolo.TipoBolo.Chocolate == tipoBolo)
{
Console.WriteLine("Pega os ingredientes do bolo de chocolate");
}
else if(EBolo.TipoBolo.Morango == tipoBolo)
{
Console.WriteLine("Pega os ingredientes do bolo de morango");
}
}
public override void Passo2()
{
if(EBolo.TipoBolo.Chocolate == tipoBolo)
{
Console.WriteLine("Mistura os ingredientes de chocolate e leva ao forno");
}
else if(EBolo.TipoBolo.Morango == tipoBolo)
{
Console.WriteLine("Mistura os ingredientes de morango e leva ao forno");
}
}
}
}
using System;
namespace DevBrasil
{
public class Padeiro
{
public void FazerBolo(EBolo.TipoBolo tipoBolo)
{
Bolo bolo = new Bolo(tipoBolo);
// chama o template method da classe BoloBase
bolo.FazerBolo();
}
}
}
using System;
namespace DevBrasil
{
public class Confeiteiro
{
public void FazerBolo(EBolo.TipoBolo tipoBolo)
{
Bolo bolo = new Bolo(tipoBolo);
// chama o template method da classe BoloBase
bolo.FazerBolo();
}
}
}
using System;
namespace DevBrasil
{
public class Program
{
static void Main(string[] args)
{
// instancia um objeto do tipo padeiro
Padeiro padeiro = new Padeiro();
padeiro.FazerBolo(EBolo.TipoBolo.Chocolate);
// instancia um objeto do tipo confeiteiro
Confeiteiro confeiteiro = new Confeiteiro();
confeiteiro.FazerBolo(EBolo.TipoBolo.Morango);
}
}
}
Nesse artigo, foi explicado como implementar um Template Method, e o quanto é importante definir a estrutura de um algoritmo numa única classe abstrata quando inúmeras classes podem precisar implementar esse algoritmo, basicamente a idéia do artigo consistiu em passar o conceito através de uma implementação simples, não envolvendo recursos complexos.