terça-feira, 7 de fevereiro de 2012

Design Patterns: Strategy

O Design Pattern (ou Padrão de Projeto) Strategy é um dos Patterns mais básicos e dá origem a diversos outros Patterns, como o Iterator, por exemplo. Ele foi concebido para separar um pedaço do algoritmo e torná-lo intercambiável permitindo que o comportamento do objeto possa ser modificado em tempo de execução, sem que seja necessário alterar as classes que executavam o comportamento anterior.

A descrição formal do Strategy é a seguinte: Define uma família de algoritmos, encapsula cada um e os torna intercambiáveis, independentemente de quem os utiliza.

Por exemplo, imagine que você tenha uma classe para validar dados. Você poderia, utilizando o Pattern Strategy, trocar o algoritmo de validação dependendo do dado que deverá ser validado (número, data, CPF, etc).

Um outro exemplo, mais elucidativo: imagine que exista uma classe Carro, ao apertar o pedal de freio, o carro deverá frear, todos os carros possuem este comportamento. Porém, um carro com freio comum se comporta de forma ligeiramente diferente de um carro com freio ABS. Neste caso, em vez de colocar o código destes dois comportamentos na classe Carro, podemos utilizar o Strategy e separar os comportamentos do freio comum e do freio com ABS. A classe Carro se encarregará de escolher o freio correto de acordo com o modelo do carro. O diagrama de classes deste exemplo seria o seguinte:


Além de isolarmos a parte do carro que muda (neste caso o freio), também temos a vantagem de, caso queiramos incluir um novo tipo de freio (FreioEBD, por exemplo), teremos apenas que criar uma nova classe que implemente a interface IFreio, e não teremos que testar novamente a classe FreioComum e FreioABS, nem o método ApertarFreio da classe Carro.

Para entender melhor, poderíamos aplicar o exemplo sobre a definição do Strategy: Define uma família de algoritmos (nossa família de algoritmos é representada pela interface IFreio), encapsula cada um (encapsulamos os tipos de freio nas classes FreioComum e FreioABS) e os torna intercambiáveis (criando o atributo Freio do tipo IFreio na classe Carro, tornamos o freio interfambiável), independentemente de quem os utiliza (quem se preocupa em escolher o freio correto é a própria classe Carro - no seu construtor, por exemplo - e quem a instancia e a utiliza não precisa se preocupar com a implementação do freio).


Nenhum comentário: