Sei sulla pagina 1di 27

Primeiros passos com Padres de Projeto

Marcos Brizeno
This book is for sale at http://leanpub.com/primeiros-passos-com-padroes-de-projeto
This version was published on 2016-02-20

This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing
process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and
many iterations to get reader feedback, pivot until you have the right book and build traction once
you do.
2016 Marcos Brizeno

Ol, esse livro foi escrito pensando em pessoas que possuem um bom conhecimento de Orientao a
Objetos e querem dar os primeiros passos com Padres de Projeto.
No iremos entrar em muitos detalhes sobre os padres, mas o meu livro Refatorando com Padres
de Projeto um excelente maneira de aprofundar os estudos.
Se voc gostar do que vai ler aqui, compartilhe o material com outras pessoas!
Se tiver qualquer feedback me avise em @marcosbrizeno.
Esse livro foi distribudo de graa e pode ser encontrado em leanpub.com.
Boa leitura!

Contedo
INTRODUO

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

O QUE UM PADRO DE PROJETO? . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


O Surgimento dos Padres de Projeto . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Os padres da Gangue dos Quatro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2
2
3

REVISITANDO A ORIENTAO A OBJETOS . . . . . . . . . . . . . . . . . . . . . . . . .


Alguns Princpios de Design Orientado a Objetos . . . . . . . . . . . . . . . . . . . . . .

4
4

EXEMPLOS DE PADRES DE PROJETO . . . . . . . . . . .

O PADRO SIMPLE FACTORY . . . . . . . . . . .


Exemplo de Aplicao . . . . . . . . . . . . . . .
Um Pouco de Teoria . . . . . . . . . . . . . . . .
Quando No Usar . . . . . . . . . . . . . . . . .
Evoluindo o Simple Factory para Factory Method
Evoluindo o Simple Factory para Builder . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

7
7
10
11
11
12

O PADRO STRATEGY . . . . . . . . . . . . .
Exemplo de Uso . . . . . . . . . . . . . . .
Um Pouco de Teoria . . . . . . . . . . . . .
Quando No Usar . . . . . . . . . . . . . .
Evoluindo o Strategy para Template Method
Evoluindo o Strategy para State . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

13
13
16
17
17
18

A ESTRADA A FRENTE

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

. . . . . . . . . . . . . . . . . . . . . . . . . . . 19

APLICANDO PADRES DE PROJETO . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


Refatorando com Padres de Projeto . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20
20

REFERNCIAS EXTERNAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

SOBRE O AUTOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

23

INTRODUO
Como desenvolvedores, ns enfrentamos vrios problemas para lidar com a informao nos sistemas:
estruturar e armazenar as informaes, transformar dados para que possam ser lidos pelos usurio,
agrupar dados de diferentes sistemas etc. Assim, desenhar um sistema e sua arquitetura nem sempre
uma tarefa simples e direta. Alm disso, conforme aprendemos mais sobre o domnio e a maneira
como o sistema utilizado, percebemos que o desenho inicial no ser suficiente e sentimos a
necessidade de modific-lo.
No entanto, a maioria dos desafios que encontramos no nico. Certamente o domnio do sistema
pode ser diferente, mas a essncia dos problemas continua a mesma: como lidar com informao.
Assim surgiu a ideia dos Padres de Projeto, como uma base coletiva de conhecimento com solues
para esses problemas comuns que encontramos todos os dias.
Ao longo deste livro vamos ver como se deu o surgimento dos Padres de Projeto e como eles
foram adaptados para o desenvolvimento de software. Em seguida vamos analisar caractersticas do
paradigma Orientado a Objetos e como eles buscam simplificar o desenvolvimento de aplicaes.
Por fim, sero explorados dois exemplos de padres voltados para o desenvolvimento Orientado a
Objetos, para exemplificar como eles podem ajudar na manuteno de sistemas.

O QUE UM PADRO DE PROJETO?


Desenvolvimento de software uma rea relativamente nova comparada com outras reas de
conhecimento. Contando a partir da Ada Lovelace como a desenvolvedora do primeiro programa
de computador e o surgimento da Mquina de Turing, ainda no temos 100 anos de histria.
Por isso, muitas das nossas prticas so emprestadas de outras reas. O maior exemplo a
Engenharia de Software onde tentamos aplicar muitas das ideias de outras Engenharia nos projetos
de desenvolvimento de software.

O Surgimento dos Padres de Projeto


O surgimento dos Padres de Projeto, por exemplo, vem da arquitetura, atravs do livro A Patter
Language escrito por Christopher Alexander, Sara Ishikawa e Murray Silverstein, do Center for
Environmental Structure of Berkeley, California, publicado em 1977.
O livro define uma linguagem chamada pelos autores de linguagem de padres, que se origina a
partir dos 253 padres apresentados no livro. O objetivo que, com essa linguagem em comum,
pessoas ao redor do mundo possam compartilhar ideias sobre como organizar bairros, cidades,
projetar casas, escritrios e quaisquer outros espaos.
Quando levamos esse conceito para o mundo do desenvolvimento, temos os Padres de Projeto
como solues de implementao para um problema em um determinado contexto. O objetivo
ao documentar as solues comumente encontradas montar um banco de conhecimento onde
pessoas com o mesmo problema podem consultar qual seria uma boa soluo.
Com o ritmo que cresce a tecnologia da informao, essa base de conhecimento se torna ainda mais
valiosa pois nos permite aprender com as experincias de outras pessoas. Mas, antes de explorar os
padres em si, importante entender como essa base de conhecimento surgiu.
O livro Padres de Projeto - Solues Reutilizveis de Software Orientado a Objetos da famosa
Gangue dos Quatro (Gang of Four em ingls) talvez a referncia mais utilizada sobre o assunto. Esse
livro popularizou os conceitos de Padres de Projeto apresentando as solues em C++ e Smalltalk,
duas linguagens com caractersticas bem diferentes e que faziam sucesso nos anos 90.
Um ponto importante sobre padres que eles no so inventados, mas sim extrados de cdigos
reais. A soluo proposta por um padro surge do conhecimento comum de vrias pessoas que
passaram pelo mesmo problema e aplicaram solues semelhantes. A maior prova disso que os
livros que documentam Padres de Projeto so geralmente escritos por vrias pessoas.
Outro bom exemplo o livro Padres de Arquitetura de Aplicaes Corporativas escrito por Martin
Fowler com a colaborao de David Rice, Mathew Foemmel, Edward Hieatt, Robert Mee e Randy
2

O QUE UM PADRO DE PROJETO?

Stafford. A diferena deste livro que os padres apresentados no so especficos para linguagens
Orientada a Objetos, mas para projetos corporativos, que precisam ser mais robustos e lidar com
problemas no triviais.
Existe tambm Padres de Projeto que propes solues para problemas especficos de uma
linguagem ou plataforma, como por exemplo o livro Core J2EE Patterns, que apresenta solues
especfica para a linguagem Java na plataforma Java 2 Enterprise Edition. Eles continuam sendo
considerados padres, a nica diferena que o contexto de sua aplicao mais restrito.

Os padres da Gangue dos Quatro


Sendo a referncia mais conhecida, bem provvel que ao ouvir falar de padres de projeto voc
escute sobre um dos 23 padres documentados pela Gangue do Quatro. Para linguagens Orientadas
a Objetos esses padres so to teis que so encontrados em muitas das bibliotecas mais utilizadas,
e alguns so aplicados at mesmo na biblioteca padro da linguagem.
Ao longo do livro os autores constroem uma aplicao para exemplificar as vrias situaes de
onde os Padres de Projeto foram extrados. Cada um deles documentando com: nome, objetivo,
motivao, contexto, soluo e o exemplo. Alm disso os padres so classificados de acordo com
a natureza do problema que tenta resolver: criar objetos (padres de criao), estruturar os objetos
(padres estruturais) ou dividir comportamento (padres comportamentais).

Padres de Criao
Factory Method, Abstract Factory, Builder, Prototype e Singleton
Os Padres de Criao tem como inteno principal abstrair o processo de criao de objetos, ou
seja, a sua instanciao. Desta maneira o sistema no precisa se preocupar com a lgica de criao
de objetos, permitindo que ela evolua independente do resto.

Padres Estruturais
Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy
Os Padres Estruturais se preocupam em como as classes e objetos so compostos, ou seja, sua
estrutura. O objetivo destes padres e facilitar o design do sistema, melhorando as maneiras de
relacionamento entre as entidades.

Padres Comportamentais
Interpreter, Template Method, Chain of Responsibility, Command, Iterator, Mediator, Memento,
Observer, State, Stratefy, Visitor
Os Padres Comportamentais atuam na distribuio das responsabilidades entre os objetos, ou seja,
como eles se comportam. Estes padres facilitam a comunicao entre os objetos, distribuindo as
responsabilidades.

REVISITANDO A ORIENTAO A
OBJETOS
A programao Orientada a Objetos um paradigma bastante disseminado entre os desenvolvedores, assim cada pessoa acaba tendo seu prprio entendimento. Ento, antes de falar sobre os padres
desse paradigma, vamos analisar as ideias do pensamento orientado a objetos e partir de um ponto
comum.
Alan Kay cunhou o termo Orientao a Objetos em 1967 e tido como o criador do paradigma. Em
um email, que a fonte de informao mais importante sobre o tema http://userpage.fu-berlin.de/
~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en, Dr. Kay explica quais foram suas motivaes iniciais
ao criar a Programao Orientada a Objetos.
Segundo sua definio, podemos entender o paradigma Orientado a Objetos em duas partes: 1)
objetos seriam como clulas biolgicas, que se comunicam apenas atravs de mensagens e 2)
esconder os dados, pois cada objeto possui sua prpria lgica para lidar com a informao sem
precisar exp-las.
Ao definir uma classe comum falar na interface do objeto como sendo a maneira como os objetos
desta classe trocam mensagens, ou seja os seus mtodos pblicos. Essa interface esconde o estado
interno do objeto e permite que o desenvolvedor foque nas interaes, simplificando o entendimento
do programa.
A primeira linguagem a aplicar esses conceitos foi Smalltalk, uma linguagem de tipo dinmico onde
no existem tipos primitivos e tudo implementado como uma classe. Ao longo do desenvolvimento
de novas linguagens, outras funcionalidades foram adicionadas, como por exemplo a herana e o
polimorfismo.
As linguagens Orientada a Objetos mais recentes tendem a misturar conceitos e funcionalidades de
diversos paradigmas, como por exemplo representar mtodos como objetos, utilizar lambdas para
passar blocos de cdigo como parmetros para outros mtodos etc. Mas por trs de todas essas
novas funcionalidades continua o pensamento de esconder os dados para facilitar a comunicao
entre objetos.

Alguns Princpios de Design Orientado a Objetos


Com a grande adoo de linguagens Orientada a Objetos, surgiram vrios princpios para guiar o
design de sistemas. Esses princpios ajudam a organizar o cdigo e facilitam a manuteno atravs
de boas prticas sobre como escrever as interaes entre os objetos.
4

REVISITANDO A ORIENTAO A OBJETOS

O conjunto de princpios que se tornou mais famoso o SOLID, criado por Robert C. Martin
(tambm conhecido na comunidade como Uncle Bob). O problema que levou a criao deles foi
a dificuldade de gerenciar dependncias entre objetos e classes, especialmente quando a aplicao
comea a crescer.
Segundo Robert, um cdigo que no consegue fazer um bom gerenciamento de dependncia se torna
difcil de manter, frgil e no reutilizvel. Em resumo, esses so os princpios e o que eles pregam:
Single Responsibility Principle (Princpio da Responsabilidade nica): Cada classe deve ter
um, e apenas um, motivo para mudar;
Open Closed Principle (Princpio Aberto Fechado): Deve ser possvel estender o comportamento de uma classe sem modific-la;
Liskov Substitution Principle (Princpio da Substituio de Liskov): Classes derivadas devem
ser compatveis com sua classe base;
Interface Segregation Principle (Princpio da Segregao de Interface): Crie interfaces mnimas
e especficas para o cliente;
Dependency Inversion Principle (Princpio da Inverso de Dependncia): Dependa de abstraes ao invs de classes concretas.
Em seu site, Robert apresenta artigos dedicados a cada um dos princpio, com motivao, exemplos
e aplicaes. Alm disso, outros princpios tambm podem ser encontrados l e a leitura recomendada para aprofundar o conhecimento no assunto: http://butunclebob.com/ArticleS.UncleBob.
PrinciplesOfOod. No meu blog, tenho uma srie de posts dedicada aos princpios solid que tambm
pode ajudar a entender melhor a importncia deles: https://brizeno.wordpress.com/solid/.
Alm do SOLID, tambm vale a pena explorar outros dois princpios de design Orientado a Objetos
que esto fortemente presentes nos Padres de Projeto:
Prefira Composio ao invs de Herana: ao herdar de uma classe estamos aumentando o nvel
de acoplamento entre elas, portanto prefervel compor objetos e criar interfaces para expor
sua lgica;
Programe voltado a Interface e no a Implementao: ao desenvolver uma classe no pense
em como ela vai funcionar, mas sim em como ela ser utilizada. Exponha interfaces que faam
sentido e simplificam seu uso.
Esses princpios foram especialmente citados aqui pois, ao refatorar o cdigo e aplicar um padro,
estamos tambm seguindo os princpios de design Orientado a Objetos.

EXEMPLOS DE PADRES DE PROJETO


Para exemplificar as principais vantagens de utilizar Padres de Projetos, foram escolhidos os
padres Simple Factory e Strategy, devido a simplicidade de utilizao e por resolverem problemas
comuns do dia-a-dia. Nos captulos seguinte vamos mostrar um exemplo de cdigo que pode se
beneficiar dos padres, mostrando como ficaria o resultado final e quais suas vantagens.
Ao estudar aplicaes de padres, o mais importante no saber como aplicar o padro ou qual
implementao utilizar. Refatorar um cdigo para aplciar um padro no to difcil quanto decidir
quando aplic-lo. Ao ver exemplos, atente para as melhorias de design que precisam acontecer e em
como indentific-las.

O PADRO SIMPLE FACTORY


Criar objetos geralmente uma tarefa simples, passamos valores para o construtor e pronto, temos
um objeto instanciado e pronto para uso. No entanto, algumas vezes a criao no to direta assim
e alguma manipulao com os dados pode ser necessria. Em outros casos preciso configurar o
objeto, mesmo depois da execuo do construtor.
Quando instanciar objetos no for uma tarefa to simples, os padres de criao oferecem boas
solues. Como vimos antes, os padres documentados pela Gangue dos Quatro foram classificados
em grupos de acordo com o tipo de problema que resolvem. Padres que facilitam criar novas
instncias de objetos so classificados como padres de criao.
Uma verso simples e que pode ser utilizada mais facilmente, o Simple Factory. Nele vamos extrair
a lgica que cria objeto para uma classe especializada, deixando que a manipulao dos dados no
atrapalhe o restante da lgica de negcio. Alguns autores nem consideram o Simple Factory como
um padro, devido a sua simplicidade.

Exemplo de Aplicao
Na Listagem 1 temos um exemplo de cdigo que pode se beneficiar do uso do Simple Factory. Nele,
o mtodo buscarProdutosPreferenciais recebe um usurio consulta um servio externo para obter os
produtos que o usurio costuma comprar. Ao final, os produtos so validados e filtrados para que
apenas aqueles com estoque sejam retornados.
No entanto, antes de chegar na lgica que realmente faz a busca dos produtos preferenciais do
usurio, preciso configurar a chamada ao servio externo. Essa responsabilidade extra aumenta o
tamanho e a complexidade do mtodo.
Listagem 1 - Mtodo que busca os produtos preferenciais de um usurio

public List<Produto> buscarProdutosPreferenciais(Usuario usuario) {


ConfiguracoesServicos config = new ConfiguracoesServicoProdutosPreferenciais();
config.setRecurso(/produtos/preferenciais/);
config.setIdUsuario(usuario.getId());
if (getAmbienteAtual() == Ambiente.LOCAL) {
config.setEndpoint(localhost:1234);
config.setXid(gerarUuid());
config.setVersaoApi(2.1);
} else {

O PADRO SIMPLE FACTORY

if (toggleApiNova.habilitado()) {
config.setVersaoApi(2.1);
config.setXid(gerarUuid());
} else {
config.setVersaoApi(1.9);
config.setXid();
}
config.setEndpoint(https://intra. + getAmbienteAtual().toString() + .mega\
corp.com/);
}
ServicoRest servico = new ServicoRest(config);
List<Produto> produtos = criarProdutos(servico.executarGet())
List<Produto> produtosValidos = new ArrayList<Produto>();
for (Produto produto : produtos) {
if (produto.temEstoque()) {
produtosValidos.add(produto);
}
}
return produtosValidos;
}

Note quantas linhas apenas a criao das configuraes toma. Isso acaba desviando a ateno da
responsabilidade principal do mtodo, que buscar os produtos preferenciais do usurio.
No exemplo anterior existem dois tipos de configuraes, uma para o ambiente local e outra para
os demais ambientes. A configurao dos ambientes remotos precisa lidar ainda com um feature
toggle, para determinar qual verso da API deve ser utilizada.
A criao de configuraes locais pode ser extrada como mostrado na Listagem 2. A identificao do
recurso comum a todos as configuraes, portanto pode ser definida j no construtor da fbrica,
assim como o id do usurio. As demais configuraes so especficas ao ambiente local, ficando
portanto dentro do mtodo criarConfiguracaoLocal.

O PADRO SIMPLE FACTORY

Listagem 2 - Classe fbrica para criar configuraes dos servios

class FabricaConfiguracaoServicos {
private ConfiguracoesServicos config;
public FabricaConfiguracaoServicoProdutosPreferenciais(String idUsuario) {
config = new ConfiguracoesServicoProdutosPreferenciais();
config.setRecurso(/produtos/preferenciais/);
config.setIdUsuario(idUsuario);
}
public ConfiguracoesServicos criarConfiguracaoLocal() {
config.setEndpoint(localhost:1234);
config.setXid(gerarUuid());
config.setVersaoApi(2.1);
return config;
}
}

A lgica para criar as configuraes de servios para outros ambientes depende do feature toggle.
Nesse caso vamos passar a informao se o toggle est ativo e o ambiente atual como parmetros.
A implementao pode ficar como na Listagem 3.
Listagem 3 - Lgica especfica para configurao de servios remotos

class FabricaConfiguracaoServicos {
public ConfiguracoesServicos criarConfiguracaoRemota(boolean usarApiNova, Ambi\
ente ambiente) {
if (usarApiNova) {
config.setVersaoApi(2.1);
config.setXid(gerarUuid());
} else {
config.setVersaoApi(1.9);
config.setXid();
}
config.setEndpoint(https://intra. + ambiente.toString() + .megacorp.com);
}
}

Para utilizar o Simple Factory vamos simplesmente substituir o cdigo dentro do if pela chamada
ao mtodo fbrica apropriado. Vamos tambm extrair essa parte em um novo mtodo, para facilitar
a leitura, como mostrado na Listagem 4:

O PADRO SIMPLE FACTORY

10

Listagem 4 - Mtodo para buscar produtos aplicando o padro Simple Strategy

public List<Produto> buscarProdutosPreferenciais(Usuario usuario) {


ConfiguracoesServicos config = criarConfiguracaoDoAmbiente(usuario)
ServicoRest servico = new ServicoRest(config);
List<Produto> produtos = criarProdutos(servico.executarGet())
List<Produto> produtosValidos = new ArrayList<Produto>();
for (Produto produto : produtos) {
if (produto.temEstoque()) {
produtosValidos.add(produto);
}
}
return produtosValidos;
}
public ConfiguracoesServicos criarConfiguracaoDoAmbiente(Usuario usuario) {
FabricaConfiguracaoServicos fabrica = new FabricaConfiguracaoServicos(usuario.\
getId());
if (getAmbienteAtual() == Ambiente.LOCAL) {
return fabrica.criarConfiguracaoLocal();
} else {
return fabrica.criarConfiguracaoRemota(toggleApiNova.habilitado(), getAmbien\
teAtual());
}
}

Apesar de simples, o ganho com a separao das responsabilidades bem grande, principalmente
na legibilidade do cdigo.

Um Pouco de Teoria
Como mencionado antes, todos os padres ajudam o seu cdigo a seguir os princpios de design
Orientado a Objetos. No caso do Simple Factory, o maior benefcio a diviso de responsabilidades
seguindo o Princpio da Responsabilidade nica.
Quem l o cdigo do mtodo buscarProdutosPreferenciais pode focar apenas em entender sua lgica,
sem ter que se preocupar em como as configuraes so criadas. Como passamos muito mais tempo
lendo cdigo do que escrevendo, essa uma grande vantagem.

O PADRO SIMPLE FACTORY

11

Outro benefcio da separao dessas responsabilidades que a maneira como as configuraes do


servio so criadas vai mudar menos do que lgica definida em buscarProdutosPreferenciais. Ao lidar
com dependncias entre classes sempre bom que uma classe dependa de outras menos provveis
de mudar.
Os testes do mtodo buscarProdutosPreferencias tambm esto validando a criao das configuraes de servios, mesmo que indiretamente. Criando uma classe especializada para isso, podemos
limitar o escopo dos testes e focar na lgica de negcio, testando a criao de configuraes em
outros testes isolados.
O Simple Factory um bom ponto de incio para separar a criao de objetos do seu uso. Como
vimos no exemplo anterior, poucas classes so criadas e a estrutura do padro bem simples. Se o
seu contexto permite isolar a maneira como objetos so criados e voc tiver que lidar apenas com
um tipo de objeto, o Simple Factory uma excelente maneira de resolver o problema.

Quando No Usar
Apesar de simples, existem situaes onde utilizar o padro Simple Factory no ajuda muito. Um
sinal bem claro de que o padro no est sendo efetivo quando a classe fbrica comea a crescer e
ter vrios mtodos para criar os mesmos produtos de maneiras diferentes. Essa talvez seja uma boa
hora para aplicar outros padres fbrica.
Nas sees seguintes vamos comparar como evoluir do Simple Factory para o Factory Method ou
para o Builder, dependendo de qual a necessidade do seu contexto. No vamos entrar em detalhes
sobre estes padres, mas outros recursos com mais detalhes sero indicados ao final do artigo (veja
a seo de Referncias Externas).

Evoluindo o Simple Factory para Factory Method


Se existem vrios mtodos que podem ser agrupados com suas prprias lgicas para criar objetos,
provavelmente nomeados com um sufixo ou prefixo em comum, talvez seja melhor utilizar o Factory
Method e separar esses grupos em outras classes fbrica.
Voltando ao exemplo anterior, imagine que ser necessrio criar configuraes para outros servios.
Ao invs de colocar tudo em um nica classe, melhor criar fbricas especializadas em construir as
configurao de cada servio. Refatorar o Simple Factory para o Factory Method vai ajudar a evitar
que a classe fbrica cresa.
Com o Factory Method, continuaremos criando objetos do tipo ConfiguracoesServicos, mas as regras
deles sero divididas em classes separadas. Essas classes fbricas seguem uma mesma interface,
garantindo que elas possam ser trocadas facilmente. Ao fim, evitamos ter uma classe fbrica com
muitas responsabilidades e, como elas so intercambiveis, conseguimos ter flexibilidade no cdigo
que as utiliza.

O PADRO SIMPLE FACTORY

12

Evoluindo o Simple Factory para Builder


Se ao rever os mtodos voc perceber que existe pouca variao na lgica entre eles, apenas mudamse os valores que so atribudos ou quais atributos so utilizados, ser necessrio criar muitos
mtodos fbrica, com muita duplicao entre si.
No exemplo anterior, imagine que vrias configuraes de servio devem ser criadas, mas a diferena
entre os mtodos o valor de alguns atributos. Nesse caso podemos utilizar o Builder para expor a
configurao dos atributos mas esconder a criao dos objetos.
Com o Builder, ao invs de definirmos o processo de como o objeto ser construdo, oferecemos
mtodos para que a classe cliente consiga configurar, de maneira simples, o produto final. Assim
evitamos criar vrios mtodos fbrica para cada possvel cenrio, sem perder a separao da
responsabilidade de criao.

O PADRO STRATEGY
Ao codificar um programa, seguimos um conjunto de regras de negcio e, muitas vezes, o fluxo precisa ser dividido em vrios caminhos. Quando o cdigo cresce com vrias regras diferentes, podemos
recorrer aos padres comportamentais para melhorar a flexibilidade e facilitar a manuteno.
Padres comportamentais vo dividir as responsabilidades para resolver problemas de complexidade
do cdigo. O Strategy um exemplo de padro comportamental que busca isolar os vrios caminhos
que o algoritmo pode seguir, facilitando escolher um fluxo especfico sem precisar se preocupar com
os outros.

Exemplo de Uso
Na Listagem 5 temos a implementao do cdigo que deve calcular os pontos que um passageiro
ganhou em voos pela companhia area. As regras variam de acordo com a distncia voada, o status
do passageiro e o tipo de bilhete comprado.
Dado um passageiro, o algoritmo busca a lista de voos que ainda no foram computados e, para
cada um deles aplica as regras de pontuao. Caso o bilhete seja de primeira classe e o passageiro
tenha a categoria diamante, a distncia total do voo ser convertida em pontos. Caso o passageiro
no seja diamante, ele receber metade da distncia em voos de primeira classe, um quarto em voos
econmicos e um dcimo em voos promocionais.
Listagem 5 - Mtodo para calcular a pontuao de um passageiro

public int calcularPontuacao(Passageiro passageiro) {


int totalDePontos = 0;
List<Voo> voosPendentes = passageiro.getVoosComPontuacaoPendente();
for (Voo voo : voosPendentes) {
Bilhete bilhete = passageiro.getBilhete(voo.getNumero());
if (bilhete.isPrimeiraClasse() && passageiro.isDiamante()) {
totalDePontos += voo.getDistancia();
} else if (bilhete.isPrimeiraClasse()) {
totalDePontos += voo.getDistancia()/2;
} else if (bilhete.isClasseEconomica()) {
totalDePontos += voo.getDistancia()/4;
} else {
// bilhete promocional

13

O PADRO STRATEGY

14

totalDePontos += voo.getDistancia()/10;
}
}
passageiro.atualizarPontuacao(totalDePontos);
passageiro.marcarVoosComoProcessados();
return totalDePontos;
}

Separando os fluxos do algoritmo, conseguimos extrair 4 estratgias: 1) voo de um passageiro


diamante na primeira classe, 2) voo na primeira classe, 3) voo na classe econmica e 4) voo
promocional.
A interface comum das estratgias bem simples e precisa apenas oferecer um mtodo que retorna
a pontuao do passageiro, dado a distncia do voo. Uma Interface poderia ser implementada
conforme a Listagem a seguir:
Listagem 6 - Interface simples para estratgias de clculo de pontuao

interface EstrategiaDePontuacao {
public int calcularPontuacao(int distanciaDeVoo);
}

A implementao das estratgias tambm bem simples e pequena, pois as regras separadas so
simples. Veja como ficaria o cdigo na Listagem 7:
Listagem 7 - Classes com implementao de estratgias seguindo a interface

class EstrategiaPrimeiraClasseDiamante implements EstrategiaDePontuacao {


public int calcularPontuacao(int distanciaDeVoo){
return distanciaDeVoo;
}
}
class EstrategiaPrimeiraClasse implements EstrategiaDePontuacao {
public int calcularPontuacao(int distanciaDeVoo){
return distanciaDeVoo/2;
}
}
class EstrategiaClasseEconomica implements EstrategiaDePontuacao {
public int calcularPontuacao(int distanciaDeVoo){

O PADRO STRATEGY

15

return distanciaDeVoo/4;
}
}
class EstrategiaPromocional implements EstrategiaDePontuacao {
public int calcularPontuacao(int distanciaDeVoo){
return distanciaDeVoo/10;
}
}

Um ponto de ateno ao aplicar o padro Strategy encontrar onde deve ser decidido qual estratgia
utilizar. Para determinar a regra de pontuao precisamos de informaes de um passageiro e do
bilhete. Vamos ento criar um mtodo na classe Bilhete que retorna qual a estratgia de pontuao
deve ser utilizada. Veja a implementao na Listagem seguinte:
Listagem 8 - Mtodo que decide qual estratgia deve ser utilizada

class Bilhete {
public EstrategiaDePontuacao getEstrategiaDePontuacao(boolean isPassageiroDiam\
ante){
if (bilhete.isPrimeiraClasse() && isPassageiroDiamante) {
return new EstrategiaPrimeiraClasseDiamante();
} else if (bilhete.isPrimeiraClasse()) {
return new EstrategiaPrimeiraClasse();
} else if (bilhete.isClasseEconomica()) {
return new EstrategiaClasseEconomica();
} else {
return new EstrategiaPromocional();
}
}
}

Agora basta que o mtodo calcularPontuacao pegue a estratgia do bilhete para definir quantos
pontos devem ser dados ao passageiro. A utilizao ficaria como mostrado na Listagem 8.

O PADRO STRATEGY

16

Listagem 9 - Clculo de pontuao utilizando as estratgias implementadas

public int calcularPontuacao(Passageiro passageiro) {


int totalDePontos = 0;
List<Voo> voosPendentes = passageiro.getVoosComPontuacaoPendente();
for (Voo voo : voosPendentes) {
Bilhete bilhete = passageiro.getBilhete(voo.getNumero());
EstrategiaDePontuacao estrategia = bilhete.getEstrategiaDePontuacao(passagei\
ro.isDiamante());
totalDePontos += estrategia.calcularPontuacao(voo.getDistancia());
}
passageiro.atualizarPontuacao(totalDePontos);
passageiro.marcarVoosComoProcessados();
return totalDePontos;
}

Ao quebrar o fluxo do algoritmo em estratgias conseguimos simplificar o mtodo calcularPontuacao


e dividir a responsabilidade de saber qual regra utilizar com a classe Bilhete. Por sua vez, a lgica
de clculo da pontuao fica definida dentro de cada uma das estratgias.
No final ganhamos maior coeso ao separar as responsabilidades, facilitando modificar e at mesmo
adicionar novas regras de pontuao.

Um Pouco de Teoria
Assim como no caso do padro Simple Factory, ao aplicar o Strategy fica bem claro a diviso
das responsabilidades, seguindo o Princpio da Responsabilidade nica. A lgica para calcular a
pontuao fica mais simples uma vez que est separada.
Aps distribuir os fluxos do algoritmo nas classes estratgias, podemos tambm mover os testes
e faz-los validar apenas uma parte do cdigo. Considerando que testes so a melhor forma de
documentao, uma nova pessoa na equipe conseguir ver o funcionamento de um fluxo de cada
vez, ao invs de todo o algoritmo.
Como a estrutura de estratgias define uma interface comum para todos, tambm fcil notar o
Princpio da Substituio de Liskov. Trocar as estratgias, ou at mesmo adicionar novas, no vai ter
nenhum impacto pois o cdigo que as utiliza continuar lidando com a mesma interface.
O Princpio da Inverso de Dependncia tambm fica claro pois o cliente no usa as estratgias
concretas diretamente, apenas uma interface. Assim, cada implementao pode ter suas prprias
regras sem interferir na estrutura do cdigo.

O PADRO STRATEGY

17

Outro ponto importante que devido ao baixo acoplamento entre a classe, fica mais fcil evoluir
os cdigos separadamente. Como as estratgias tendem a mudar menos do que o cdigo do cliente,
tambm seguimos a ideia de que uma classe deve depender de outras menos provveis de mudar.

Quando No Usar
Semelhante ao padro Simple Factory, o Strategy uma excelente maneira de comear a refatorar
seu cdigo. Mas, devido a sua simplicidade, eventualmente pode ser necessrio partir para solues
mais robustas e evitar que as estratgias cresam sem limite.
Como em qualquer padro, importante entender o contexto do problema para identificar a melhor
soluo. Se o contexto muda, a soluo provavelmente mudar. Existem duas grandes necessidades
de contexto para aplicar o Strategy de maneira efetiva: 1) os fluxos do algoritmo podem ser separados
de maneira independente e 2) uma vez que sabemos qual caminho seguir, ele no muda at o final
da execuo do algoritmo.
Nas sees a seguir vamos comparar o Strategy com os padres Template Method e State, que podem
ajudar quando um dos contextos detalhados anteriormente no puder ser cumprido. No vamos
entrar em detalhes sobre a implementao destes padres, mas recursos com mais detalhes sero
indicados ao final do artigo (veja a seo de Referncias Externas).

Evoluindo o Strategy para Template Method


Garantir que o fluxo do algoritmo possa ser separado nem sempre possvel. A vezes as regras que
voc precisa aplicar no vo permitir que o algoritmo seja quebrado em fluxos diferentes. Uma ideia
para comear e validar essa possibilidade tentar duplicar o cdigo entre as estratgias.
Se o algoritmo separado precisar de muita duplicao, talvez a separao em estratgias no seja a
melhor opo. Os ganhos obtidos com a flexibilidade da soluo no vo compensar os gastos com
a manuteno de cdigo repetido. Nesses casos, outros padres podem ajudar a resolver o problema,
como o Template Method.
Ao aplicar o Template Method definimos uma estrutura base, que ser comum a todas as variaes
de fluxos, alm de vrios pontos gancho onde podemos variar a implementao. Dessa forma os
pontos comuns ficam centralizados na classe me e as classes filhas podem implementar sua prpria
lgica se beneficiando do algoritmo base.
Caso fosse necessrio aplicar uma mesma regra em todas as diferentes estratgias (por exemplo,
incluir um bnus de 10% para primeiras compras), essa regra precisaria ser duplicada. Poderamos
definir um template que calcula a pontuao baseado na distncia, regra que seria definida pelas
classes filhas, e sempre adiciona essa bonificao extra ao final.

O PADRO STRATEGY

18

Evoluindo o Strategy para State


Com relao a segunda necessidade de contexto, precisamos garantir que uma vez que a estratgia
definida ela no mudar, j que a principal vantagem de utilizar o Strategy diminuir a quantidade
de decises que precisam ser tomadas. Se for preciso fazer vrias verificaes em pontos diferentes
para descobrir qual estratgia utilizar, ou modificar a estratgia atual, a aplicao do padro no
ajudar muito.
Na maioria das vezes preciso revisitar todo o algoritmo para tentar fazer com que essa deciso s
acontea uma vez. No entanto, caso as regras do algoritmo realmente precisem que o fluxo mude no
meio do caminho, pode ser melhor aplicar o padro State.
Assim como no padro Strategy, o State tambm sugere dividir os fluxos do algoritmo mas, ao invs
de escolher uma estratgia a ser seguida, criamos estados contendo suas informaes e regras.
Esses estados sero facilmente trocados, conforme necessrio, pois cada um deles saber qual deve
ser o prximo estado a ser chamado, bem semelhante a uma Mquina de Estados Finita. Assim no
precisamos nos preocupar em escolher qual estado utilizar, basta configurar o ponto de partida.
Poderamos evoluir o cdigo do exemplo anterior para o State caso os status do passageiro tivessem
uma maior influncia (por exemplo, se para cada status um multiplicador de pontuao diferente
fosse aplicado). Ao invs de fazer com que cada estratgia adicione vrios ifs para saber o que fazer
dependendo do passageiro, cada status seria mapeado para um estado que saberia aplicar suas regras
bem como quando o passageiro evoluiu para um novo estado.

A ESTRADA A FRENTE
Com os padres apresentados aqui, espero que voc tenha uma ideia melhor das vantagens de utilizlos e dos benefcios que eles proporcionam.
Padres de Projeto so uma excelente ferramenta pois, alm dos benefcios no cdigo, eles tambm
facilitam as conversas dentro do time. Se uma pessoa disser que refatorou aquele cdigo que estavam
trabalhando ontem pra utilizar um Simple Factory, voc j sabe o que foi feito sem precisar entrar
em muitos detalhes de como foi implementado.
Como explorado no comeo do artigo, existem vrios livros que apresentam padres para linguagens
Orientada a Objetos e outros mais especficos para plataformas e linguagens. Procure o material que
melhor se adequa ao seu contexto e continue aprendendo sobre essas solues.

19

APLICANDO PADRES DE PROJETO


Utilizar padres de projeto tambm tem suas desvantagens, a principal que eles criam uma
estrutura um tanto quanto complexa de classes, utilizando-se de herana e delegando chamadas
para dar ao cdigo final mais flexibilidade na sua utilizao e manuteno.
Criar muitas classes no necessariamente algo ruim, lembre-se da discusso no comeo do artigo: a
ideia do paradigma Orientado a Objetos esconder os dados e facilitar a interao entre objetos. Se
voc est utilizando uma linguagem Orientada a Objetos, no deve ter medo de criar novas classes
ou extrair partes do comportamento, mas importante saber quando vale a pena faz-lo.
Apesar do cdigo ficar mais simples, separado em pequenos mtodos, quem no conhece os padres
vai precisar entender as vrias classes que so criadas e seguir o fluxo do cdigo para entender o
que est acontecendo.
A principal dica para utilizar Padres de Projeto de maneira eficiente : evite escrever cdigo
aplicando um Padro de Projeto, prefira refatorar para um padro. Se o cdigo no precisa da
flexibilidade proporcionada pelos padres, evite complic-lo.
Deixe que seu cdigo evolua e que as regras de negcio lhe digam o que deve ser melhorado. Quem
desenvolve utilizando TDD (Test-Driven Development) pode pensar em aplicar um padro durante
a etapa de refatorao, pois ter mais entendimento dos requisitos e da implementao necessria,
alm da segurana dos testes automatizados.
Antes de decidir refatorar o cdigo para aplicar um Padro de Projeto, veja quais princpios ele
est ferindo e tente fazer correes mais simples. No se torne um dicionrio de padres, forando
situaes para aplic-los. Pense no contexto do seu problema primeiro e depois na soluo que ir
aplicar.

Refatorando com Padres de Projeto


Quando o seu contexto realmente permitir aplicar um padro, v em frente e refatore o cdigo. D
pequenos passos, sempre atualizando testes e garantindo que tudo continua funcionando. Encare os
Padres de Projeto como um destino final de uma caminhada que comea com pequenos passos de
refatorao.
Outra grande vantagem dos Padres de Projeto que eles so solues que foram aplicadas por
vrias pessoas e, como ainda so conhecidos at hoje, resolvem bem o problema. Ento ao aplicar
um padro voc est utilizando um cdigo que j foi validado por vrias pessoas em vrios projetos
diferentes.
No artigo Is Design Dead, (veja a seo de Referncias Externas) Martin Fowler sugere alguns pontos
para aproveitar ao mximo os padres de projeto:
20

APLICANDO PADRES DE PROJETO

21

Invista tempo aprendendo sobre padres;


Concentre-se em aprender quando aplic-los (no muito cedo);
Concentre-se em como implementar padres na sua forma mais simples, e adicionar complexidade depois;
Se voc adicionar um padro, e depois perceber que ele no est ajudando, no tenha medo
de remov-lo.
No livro Refatorando com Padres de Projeto so apresentados vrios padres, tendo como plano
de fundo um cdigo que ser refatorado para aplicar um padro. Se quiser se aprofundar mais no
tema, leia mais em: http://www.casadocodigo.com.br/products/livro-refatoracao-ruby

Livro Refatorando com Padres de Projeto

Espero que o contedo apresentado possa ajudar nos primeiros passos e que tenha lhe motivado a
ir mais longe. No deixe de conferir os recursos indicados no final do texto para ter uma viso mais
aprofundada do contedo e saber quais so os prximos passos.

REFERNCIAS EXTERNAS
http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en
Email do Dr. Alan Kay sobre a origiem da Programao Orientada a Objetos
http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
Artigos sobre Princpios de Design Orientado a Objetos no site de Robert C. Martin
http://martinfowler.com/articles/designDead.html
Artigo Is Design Dead no site de Martin Fowler
http://casadocodigo.com.br/products/livro-refatoracao-ruby
Livro Refatorando com padres de projeto de Marcos Brizeno
https://brizeno.wordpress.com/padroes
Exemplos com outros padres da Gangue dos Quatros no site de Marcos Brizeno

22

SOBRE O AUTOR
Cientista da Computao pela Universidade Estadual do Cear e Consultor de Desenvolvimento na
ThoughtWorks Brazil. Apaixonado por Engenharia de Software e Metodologias geis.
Autor do livro Refatorando com Padres de Projetos e com contribuies no Thoughtworks
Antologia Brasil e Prticas e Tendncias em Testes.
Publica regularmente no blog brizeno.wordpress.com e em @marcosbrizeno.

https://www.casadocodigo.com.br/products/livro-refatoracao-ruby
https://www.casadocodigo.com.br/pages/sumario-thoughtworks-antologia
https://info.thoughtworks.com/praticas-e-tendencias-em-teste-ebook.html
https://brizeno.wordpress.com
https://twitter.com/marcosbrizeno

23

Potrebbero piacerti anche