Design Patterns - Parte 2 - Artigo .Net Magazine 48

Neste artigo vamos abordar dois padrões: Template Method e Decorator.

No primeiro artigo desta série vimos o que são design patterns e porque utilizá-los. Vimos também um dos padrões mais importantes e também um dos mais simples: o padrão Strategy e o aplicamos a um exemplo real. Neste artigo vamos abordar dois padrões não menos importantes: Template Method e Decorator.

O padrão Template Method vai nos ajudar a garantir que os desenvolvedores trabalhando em uma aplicação (muitas vezes nós mesmos) não esqueçam nenhum passo de determinada operação através do encapsulamento de um algoritmo. Já o padrão Decorator vai nos mostrar como compor algoritmos de forma que possamos acumular comportamentos.

Relembrando o Strategy

Vimos no artigo anterior que é importante encapsular o que muda. Foi o que fizemos quando percebemos que o cálculo de impostos mudaria de acordo com diversas regras e o separamos do método de fechar uma nota fiscal (NF). Encapsular é algo muito interessante, soa bonito, e as pessoas se interessam quando falamos nisso, então vamos explorar essa ideia um pouco mais.

Veja na Listagem 1 o código base da classe de NFs, de interface e suas implementações, onde o padrão Strategy foi aplicado (ligeiramente modificado desde o último artigo). A Figura 1 mostra o diagrama de classes.

'classe base, com o padrão Strategy aplicado, delegando 'o trabalho de cálculo de imposto à interface IInfoImposto Public MustInherit Class NFSemDP Protected _Imposto As IInfoImposto Private _decTotalNF, _decTotalImpostos As Decimal Private _blnFechada As Boolean = False Public Property Imposto() As IInfoImposto Get Return _Imposto End Get Set(ByVal value As IInfoImposto) _Imposto = value End Set End Property Public Property TotalNF() As Decimal Get Return _decTotalNF End Get Set(ByVal value As Decimal) If _blnFechada Then Throw New Exception("NF Fechada") End If _decTotalNF = value End Set End Property Public Property TotalImpostos() As Decimal Get Return _decTotalImpostos End Get Private Set(ByVal value As Decimal) _decTotalImpostos = value End Set End Property Public MustOverride ReadOnly Property Local() As String Public Sub FechaNF() TotalImpostos = Imposto.CalculaImposto(Me.TotalNF) _blnFechada = True End Sub End Class 'implentação simples da classe de imposto para a cidade de gramado Public Class NFGramado Inherits NFSemDP Public Sub New() _Imposto = New ImpostoRS End Sub Public Overrides ReadOnly Property Local() As String Get Return "Gramado" End Get End Property End Class 'interface simples de imposto, apenas com o método de cálculo Public Interface IInfoImposto Function CalculaImposto(ByVal decValorNF As Decimal) As Decimal End Interface 'implementação da classe de impostos para todo o RS, utilizada pela cidade de gramado Public Class ImpostoRS Implements IInfoImposto Public Function CalculaImposto(ByVal decValorNF As Decimal) As Decimal Implements IInfoImposto.CalculaImposto Const decAliquotaICMS@ = 0.12D Const decAliquotaISS@ = 0.03D Return Decimal.Round(decValorNF * decAliquotaICMS) + Decimal.Round(decValorNF * decAliquotaISS, 2) End Function End
Listagem 1. Classe da Nota Fiscal apenas com padrão Strategy aplicado
Figura 1. Diagrama de classes apenas com padrão Strategy

Note que a implementação das classes concretas de cálculo de imposto (ImpostoSP, ImpostoRS e ImpostoBA) pouco importa à classe de imposto e suas herdeiras. Tudo que elas querem é chamar o método CalculaImposto. A classe ImpostoSP é praticamente igual à classe ImpostoRS, mudando apenas as alíquotas, e um imposto a mais (Imposto IXYZ). Veja-a na Listagem 2.

Public Class ImpostoSP Implements IInfoImposto Public Function CalculaImposto(ByVal decValorNF As Decimal) As Decimal Implements IInfoImposto.CalculaImposto Const decAliquotaICMS@ = 0.18D Const decAliquotaISS@ = 0.05D Const decAliquotaIXYZ@ = 0.01D Return Decimal.Round(decValorNF * decAliquotaICMS) + Decimal.Round(decValorNF * decAliquotaISS, 2) + Decimal.Round(decValorNF * decAliquotaIXYZ, 2) End Function End Class
Listagem 2. Classe de cálculo de impostos – muito semelhante à anterior (ImpostoRS)

Veja agora que a classe ImpostoBA tem 2 métodos a mais, ambos privados e com função de auxiliar no cálculo dos impostos. Diferentemente da classe ImpostoRS e ImpostoSP, ela foi codificada mais explicitamente. Veja sua implementação na Listagem 3.

" [...] continue lendo...

Artigos relacionados