Behavioral Pattern – Template Method
Design Patterns é uma coleção de padrões de desenho de software que descrevem soluções para problemas já conhecidos e tidos como caso de sucesso.
Em 1995 um grupo de quatro profissionais escreveram um livro chamado “Design Patterns: Elements of Reusable Object-Oriented Software”, cujo os autores ficaram conhecidos como: “A Gangue dos Quatro” (“Gang of Four” ou GoF), sendo eles: Erich Gamma, Ralph Johnson, John Vlissides e Richard Helm.
As Design Patterns contém 23 padrões que estão divididos em três seções:
- Creational (Criacional)
- Structural (Estrutural)
- Behavioral (Comportamental)
Neste artigo abordaremos sobre a Pattern Template Method que está contida dentro da seção Behavioral (Comportamental).
Segundo o GoF, Template Method define um esqueleto de algum algoritmo em um método, adiando a implementação dos passos deste algoritmo para as sub-classes. Esses métodos que são criados nesta classe são chamados de Primitive Operations (Operações Primitivas), e o método em que este algoritmo é implementado o chamamos de Template Method.
Nesta Pattern temos no mínimo dois participantes envolvidos que veremos abaixo:
- Classe Abstrata: Define as operações primitivas (como métodos abstratos), e o Template Method que definirá o esqueleto do algoritmo.
- Classe Concreta: Qual implementa as operações primitivas.
O diagrama abaixo ilustrará estes participantes:
|
Figura 1 - Participantes do Template Method. |
Como podemos ver no diagrama acima, a AbstractClass define os métodos abstratos (Primitive Operations) que devem ser implementados nas sub-classes. Além disso, a AbstractClass ainda define um Método Template, que por sua vez irá estruturar as chamadas aos métodos (Primitive Operations), criando assim o esqueleto do algoritmo.
Vamos transformar este Pattern em um exemplo do mundo real. O cenário será: uma classe Autenticacao qual define os seguintes métodos primitivos: VerificaSintaxe e VerificarExistencia e um Template Method chamado Login. A classe não poderá ser instanciada, somente herdá-la. Ficará a cargo das classes que herdarem esta classe, implementarem estes métodos primitivos:
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
|
|
Public MustInherit Class Autenticacao |
|
Protected MustOverride Function VerificaSintaxe(ByVal password As String) As Boolean |
Protected MustOverride Function VerificarExistencia(ByVal password As String) As Boolean |
|
Public Function Login(ByVal password As String) As Boolean |
If VerificaSintaxe(password) Then |
Return VerificarExistencia(password) |
End If |
Return False |
End Function |
|
End Class |
|
|
Código 1 - Classe Base que implementa o Template Method.
|
Como podemos ver a classe Autenticacao (AbstractClass) criamos os métodos abstratos e o Template Method. Notem que no Template Method (Login) definimos o esqueleto do algoritmo, fazendo chamadas as nossas operações primitivas.
A keyword MustInherit impossibilita da classe Autenticacao ser instanciada, podendo somente ser herdada. Já a keyword MustOverride obriga implementar o método nas sub-classes. Chamo a atenção aqui que por padrão em VB.NET, os métodos são NotOverridable, ou seja, não podem ser sobreescritos nas sub-classes, garantindo assim que o método Login não será alterado (sobreescrito).
Agora nos resta implementar esta classe:
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
|
|
Public Class Cliente |
|
Inherits Autenticacao |
|
Protected Overrides Function VerificarExistencia(ByVal password As String) As Boolean |
Select Case password |
Case "Daniel", "Luciano", "Rodrigo", "Israel" |
Return True |
Case Else |
Return False |
End Case |
End Function |
|
Protected Overrides Function VerificaSintaxe(ByVal password As String) As Boolean |
Return (password.Length> 5) |
End Function |
|
End Class |
|
|
Código 2 - Classe Filha que herda da Classe "Autenticacao".
|
Como dito anteriormente, na classe Cliente herdamos a classe Autenticacao e implementamos os métodos primitivos VerificarExistencia e VerificaSintaxe de acordo com a nossa necessidade ou com as regras de negócio. Podemos aqui reparar a flexibilidade, pois poderíamos implementar de forma diferente para a uma outra classe, por exemplo, Usuarios.
E finalmente, verificando a existência de um Cliente na aplicação:
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
|
|
Sub Main() |
Dim x As New Cliente |
|
Console.WriteLine(x.Login("Joao")) |
"Output: False - Sintaxe incorreta |
|
Console.WriteLine(x.Login("Israel")) |
"Output: True - Usuário encontrado | |
Console.WriteLine(x.Login("Juliano")) |
"Output: False - Usuário inválido |
|
Console.ReadLine() |
End Sub |
|
|
Código 3 - Consumindo a classe "Cliente".
|
Ainda poderá existir ocasiões onde será necessário a criação de mais um passo dentro do seu algoritmo. Com isso basta inserir uma Operação Gancho (Hook Operation) no método Template:
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
|
|
"... |
|
Public Function Login(ByVal password As String) As Boolean |
If VerificaSintaxe(password) Then |
LogAcesso(password) |
Return VerificarExistencia(password) |
End If |
Return False |
End Function |
|
Protected Overridable Sub LogAcesso(ByVal password As String) |
Console.WriteLine("Usuario: " & password) |
End Sub |
|
"... |
|
|
Código 4 - Adicionando um metodo "Hook".
|
Quando adicionamos um método “Hook”, devemos possibilitar que ele seja sobreescrito, daí o “Gancho”, pois com isso podemos reescrever o método para uma classe específica, tendo assim maior flexibilidade. A keyword Overridable permite que o método seja sobreescrito nas sub-classes (para sobreescrever, devemos utilizar a keyword Overrides)(VB.NET).
CONCLUSÃO: Com este artigo vimos a simplicidade e flexibilidade de como construirmos aplicações Orientadas à Objetos, ganhando facilidade na manutenção devido ao encapsulamento e abstração. Há ainda mais 22 outras Patterns, que quando não nos fornece a solução por completa, ao menos nos mostra o caminho dela.
|