Você está na página 1de 28

Guia de consulta rápida

Design Patterns

Herval Freire de Albuquerque Júnior

Versão 0.5
Introdução
A Orientação a Objetos foi um dos grandes saltos de paradigma no campo do projeto e
desenvolvimento de sistemas de software, e trouxe consigo uma gama de novas idéias e
conceitos que facilitaram a análise e formalização dos sistemas. Com a ampla adoção da
Orientação a Objetos, entretanto, surgiram uma infinidade de situações-problema: modelagens
que levavam à queda de performance, sistemas inflexíveis graças a modelagens errôneas e
códigos de difícil manutenção.
Foi para reduzir o impacto destes problemas e incentivar a adoção de modelagens de
qualidade aceitável, surgiram os Padrões de Projeto – soluções documentadas para problemas
comuns encontrados no processo de modelagem de um sistema.
De maneira inversa, o conceito de Anti-Patterns enumera o conjunto de soluções e
processos que tendem a piorar os problemas de desenvolvimento. De decisões gerenciais a
detalhes de implementação de funcionalidades, os anti-patterns mostram diversas situações
que causam dor-de-cabeça aos analistas, gerentes e desenvolvedores e propõem soluções para
estes problemas, de forma a salvar o projeto antes que tudo venha a fugir do controle.
O conhecimento aprofundado de padrões e contra-padrões é uma necessidade inerente
a todo profissional que deseje aventurar-se no mundo do desenvolvimento de software. Munida
de um conjunto de regras e anotações feitas por profissionais que já enfrentaram problemas
similares, a equipe de desenvolvimento encontrará a melhor forma de resolver situações que
outrora tomariam tempo ou mesmo levariam ao fracasso do projeto.

Sobre este Guia de Consulta

O conteúdo deste guia de consulta rápida resume e enumera uma série de teorias e
modelos propostos por diversos autores de renome do ramo da Engenharia de Software. O
catálogo de padrões e anti-patterns disposto neste livro contém soluções registradas por seus
devidos autores e apenas resume as principais idéias e métodos de forma a ser uma referência
concisa de idéias, de forma que a referência aos autores de cada padrão encontra-se ao final
da publicação. Para maior aprofundamento em quaisquer tópicos mostrados neste livro,
consulte os livros dos respectivos autores.
Padrões de Projeto (Design Patterns)
De maneira simplificada, um padrão é a documentação de um problema conhecido e
sua solução em um determinado contexto. Um padrão apresenta uma solução para um
problema comum em um determinado contexto. A solução é apresentada de maneira abstrata
e descreve como um conjunto de elementos (objetos e classes, no caso dos Padrões de Projeto)
pode ser organizado de forma a solucionar o problema da melhor maneira possível. Bons
Padrões de Projeto não são somente uma estratégia de como se atacar um problema: eles
representam soluções mais confiáveis e comprovadas para problemas em seu contexto
específico, induzem à melhor reutilização de componentes de software e a um melhor
aproveitamento do sistema através da organização de seus recursos.

Origens dos Padrões de Projeto


Nos anos setenta, Christopher Alexander descreveu em livros as primeiras idéias a
respeito de padrões de projeto nas áreas da engenharia civil e da arquitetura. A idéia de
Alexander - construir sistemas arquitetônicos complexos baseados em padrões bem
conhecidos e comprovadamente funcionais - foi fonte de inspiração para diversos cientistas da
computação, que logo adotaram a idéia de padrões para o desenvolvimento de software.
Originados no final dos anos 80, os padrões de projeto para a engenharia de software
foram fruto do trabalho paralelo de vários autores: Ward Cunningham e Kent Beck
desenvolveram um conjunto de padrões para desenvolvimento de aplicações em SmallTalk,
enquanto Jim Coplien desenvolvia, no mesmo período, um catálogo de padrões para C++,
conhecidos como idiomas.
Os padrões em software foram popularizados realmente com o lançamento do livro
Design Patterns: Elements of Reusable Object-Oriented Software, de Erich Gamma, Richard
Helm, Ralph Johnson e John Vlissides (conhecidos como “Gang of Four”, ou simplesmente GoF).
O livro - uma coletânea de padrões advindos de diversos autores, lançada em 1994.

Motivação para Utilização de Padrões


Existem diversos argumentos a favor da adoção de Padrões de Projeto na modelagem
de sistemas:
• A adoção de padrões enriquece a documentação do projeto e dá um significado
semântico a construções do sistema, permitindo o rápido entendimento de estruturas
baseadas no conceito fundamentado pelos padrões;
• Os padrões promovem a reutilização de código;
• Os padrões reduzem o tempo necessário para a adaptação a uma determinada
biblioteca ou estrutura: tendo em vista que certos padrões de projeto foram adotados, é
mais fácil compreender a organização do subsistema

Tipos de Padrões
De acordo com o livro Patterns of Software Architecture, podemos dividir os padrões em
três categorias:

• Padrão de Arquitetura (Architectural Pattern) - esquema de organização


estrutural de sistemas, incluindo regras para organizar os relacionamentos entre
subsistemas e definir suas responsabilidades. Estes padrões afetam as propriedades
globais de um sistema e sua organização como um todo.
• Padrão de Projeto (Design Pattern) - um esquema de refinamento de subsistemas e
componentes do software, e dos relacionamentos entre eles. Os Padrões de Projeto
descrevem situações que se repetem, e soluções para problemas em contextos
específicos. Segundo Erich Gamma, os Padrões de Projeto podem ser classificados ainda
em famílias de padrões relacionados:
o Padrões de Criação (Creational patterns) - padrões que abstraem o
processo de instanciação de objetos. Eles ajudam a tornar modular e flexível a
criação, composição e representação de objetos do sistema.
o Padrões Estruturais (Structural patterns) - padrões que trabalham a forma
como classes e objetos são compostos em estruturas maiores. Estes padrões
lidam com formas de adaptação e interfaceamento entre componentes de uma
estrutura maior.
o Padrões Comportamentais (Behavioral patterns) - padrões que definem a
atribuição de responsabilidades entre objetos e a correta implementação de
algoritmos. Estes padrões lidam com as interações dinâmicas entre grupos de
classes e objetos, de forma a facilitar o entendimento fluxos de dados
complexos.
• Idioma (Idiom) - um padrão de baixo nível, específico a uma linguagem de
programação.

Catálogo de padrões
No catálogo de Padrões a seguir, a descrição dos padrões tem a seguinte forma:
• Nome e Classificação – Um identificador do conceito e da essência do padrão, que
permitirão identifica-lo com facilidade;
• Objetivo – O que faz o padrão e que problemas ele visa atacar;

• Solução – Seqüência de passos necessários para a implementação e utilização de um


padrão dado;
• Diagramas - Representação gráfica do padrão utilizando a técnica de modelagem de
objetos, utilizando notação UML;
• Conseqüências – Os resultados, pontos fortes e fracos advindos da adoção do padrão;

• Padrões relacionados - Outros Design Patterns que possuem alguma relação com o
padrão exposto.
Abstract Factory
Creational Pattern

Objetivo: prover uma interface que permita a criação de grupos de objetos relacionados ou
dependentes sem especificar suas classes concretas.

Solução:
•Crie uma interface Abstract Factory com Factory Methods para criação de cada tipo de
classe Product a ser instanciada.
•As subclasses da Abstract Factory implementam os métodos de criação e definem como
objetos específicos (SpecificProducts) devem ser instanciados.

Diagramas:
Diagrama de Classes
Client

ProductX AbstractFactory
Product Y
FactoryMethodX()
FactoryMethodY()

Spec ific Product Y

SpecificFactory
SpecificProduct
FactoryMethodX()
FactoryMethodY()

Consequências:
•Mantém o sistema (cliente) isolado da forma como seus produtos (Products) são criados,
compostos e representados.
•Projeta um sistema capaz de trabalhar com várias famílias de produtos (SpecificFactories
diversas) sem grandes mudanças no código.
•Força a utilização em conjunto de uma família de objetos.
•Criação de novos produtos é dificultada, pois os tipos de produtos são fixados pela
Abstract Factory: novos produtos requerem novos métodos de fabricação (Factory
Methods), o que requer modificação em todas as subclasses da Abstract Factory (todas as
SpecificFactories implementadas).

Padrões Relacionados:
Uma Abstract Factory é geralmente implementada utilizando Factory Methods ou Prototypes.
Fábricas geralmente possuem uma única instância, sendo construídas utilizando o padrão
Singleton. O padrão Builder pode substituir uma Abstract Factory ou ser utilizado em conjunto
com a mesma em diversas situações.
Adapter
Structural Pattern

Objetivo: Converter a interface de uma classe em uma outra interface esperada pelo cliente
ou modificá-la para permitir correta utilização no sistema.

Solução:
•Crie uma classe abstrata que forneça os métodos de que o cliente necessita (Interface),
•Crie uma subclasse adaptadora (Adapter) que estenda a interface abstrata,
•Faça a classe adaptadora (Adapter) estender também a classe-alvo (Target) através de
herança múltipla ou faça com que a adaptadora receba uma instância da classe-alvo
(composição),
•Sobrescreva os métodos da classe de interface na classe adaptadora para invocá-los na
classe-alvo.

Diagramas:
Diagrama de Classes (utilizando herança múltipla)
Interface Target
Client

request() s pe cifi cR equest()

implementation

Adapter request() {
specificReques t()
request() }

Diagrama de Classes (utilizando composição)


Inte rface request() {
Cl ien t adapteee.specificRequest()
}
request()

Ada pter +adaptee Target

req ues t() spec ifi cRequ est()

Conseqüências:
•Minimiza o número de novos objetos requeridos,
•Força objetos (targets) a se comportar de acordo com um padrão já definido (interface),
•A classe adaptadora pode sobrescrever funcionalidades da classe-alvo,
•A implementação utilizando herança múltipla não permite que sejam adaptadas
subclasses da classe-alvo (diferentemente da implementação por composição)

Padrões Relacionados:
O padrão Bridge tem estrutura similar ao Adapter, apesar do objetivo diferenciado (separar
interface de implementação). O padrão Decorator acrescenta funcionalidades a um objeto sem
modificar sua interface, tornando-o mais natural que o Adapter para uso na aplicação. Proxy
também define um representante para outro objeto sem mudar sua interface.
Bridge
Structural Pattern

Objetivo: Desacoplar uma abstração de sua implementação para que as duas partes possam
variar independentemente.

Solução:
•Crie uma classe de implementação (Implementor) que defina uma interface pública,
•Crie subclasses da implementação para cada tipo de implementação desejado,
•Creia uma classe de abstração (Abstraction) que mantenha uma associação com a
implementação e disponibilize um conjunto de funções para acessar as operações,
•Sempre que for necessário utilizar uma implementação, crie subclasses concretas da
abstração.

Diagramas:
Diagrama de Classes
Abstraction +impl Implementor

o perati on() op erationImpl ()

operation() {
impl.operationImpl()
}

ConcreteImplA ConcreteImplB
RefinedAbstraction
operationImpl() operationImpl()

Conseqüências:
•Evita acoplamento permanente entre abstrações e implementações
•Esconde a implementação de uma abstração do cliente
•Permite que uma mesma implementação sirva para várias abstrações de forma
transparente ao cliente
•Mudanças na implementação não afetam diretamente o cliente
•Tanto abstrações quanto implementações devem ser estendidas por herança

Padrões Relacionados:
Um Brigde pode ser construído utilizando-se um Abstract Factory.
Builder
Creational Pattern

Objetivo: Separar a construção de objetos complexos de sua representação, de forma que um


mesmo processo de construção possa criar diversas representações distintas.

Solução:
•Crie uma classe abstrata Builder que implemente Factory Methods para construção de
cada parte de um componente
•Extenda a classe Builder e implemente os Factory Methods na subclasse (SpecificBuilder)
•Utilize a classe Diretora (Director) para invocar os métodos de criação de partes definidos
pela classe Builder e retornar a estrutura completa do objeto para o cliente.

Diagramas:
Diagrama de Classes
Builder
Director
Build PartX()
Build() Build PartY()

para c ada objeto obj na es trutura {


se obj.t ype = PartX entao
Builder.BuildPartX SpecificBuilder

se objtype = PartY entao SpecificProduct


BuildPartX()
Builder.BuildPartY BuildPartY()
} GetResult()

Diagrama de Seqüência
Client Director SpecificBuilder

new SpecificBuilder()

new Director(specificBuilder)

Build() BuildPartX()

BuildPart Y()

GetResult()

Consequências:
•Mantém o algoritmo de criação de objetos complexos independente das partes e de como
elas são montadas
•Permite que o processo de construção possa gerar diferentes representações para o objeto
construído através de SpecificBuilders distintos.
•Mantém o algoritmo de montagem de objetos complexos separado do código do cliente

Padrões Relacionados
O padrão Abstract Factory pode ser adotado em substituição ao Builder, quando o objeto que
se deseja instanciar não tiver uma estrutura muito complexa. Builders são geralmente
utilizados para produzir Composites.
Chain of Responsibility
Behavioral Patterns

Objetivo: Evitar acoplamento entre emissor e receptor de uma mensagem permitindo que
mais de um objeto possa responder à requisição. Encadeia os objetos recebidos e desloca-os
através da corrente até que alguém possa manipula-lo.
Command
Behavioral Pattern

Objetivo: Encapsular uma requisição como um objeto, permitindo chamadas com


parametrização de diferentes requisições encapsuladas em objetos
Composite
Structural Pattern

Objetivo: Compor objetos em uma estrutura de árvore de forma a representar hierarquias


“parte-todo” de forma que o cliente possa tratar partes e o todo de maneira semelhante sem
precisar conhecer a diferença entre composições e nós.

Solução:
•Crie uma classe abstrata componente (Component) que defina a interface para todos os
objetos da árvore e implemente comportamento comum
•Estenda a classe componente e crie uma classe de composição concreta (Composite) que
implemente o comportamento necessário para manter e acessar coleções de nós-filhos
•Estenda a classe componente e crie uma classe para representar nós que não comportem
outros objetos (Leafs)

Diagramas:
Diagrama de Classes
Component

Client add(Component c)
remove(Component c)
getChild(identifier)
operation()

Leaf
Composite
operation()
add(component c)
operation() { remove(Component c)
getChild(identifier) +children
for each child in children {
operation()
child.operation()
}
}

Conseqüências:
•Permite ao cliente tratar partes de um todo de maneira semelhante
•O cliente pode executar as operações definidas pelo componente nos nós ou nos
compositores sem precisar saber o tipo do elemento em uso
•Define uma hierarquia que permite a associação em árvores na forma 1-para-N
•Permite a adição de novos componentes com facilidade, bastando extensões da classe
compositora ou nó. Isto também é uma desvantagem, já que se torna difícil restringir a
adição de novos componentes na hierarquia.

Padrões Relacionados:
Iterators podem ser utilizados para percorrer Composites. O padrão Flyweight permite
compartilhar componentes. Visitor localiza operações e comportamento que de outra forma,
seriam distribuídos entre Composites e folhas (Leafs). O padrão Decorator é geralmente
utilizado em conjunto com o Composite em diversos casos. Chain of Responsability utiliza-se
com freqüência de composições para implementar comportamento.
Decorator
Structural Pattern

Objetivo: Adicionar responsabilidades a um objeto dinamicamente, sem necessidade de


criação de subclasses e de maneira que seja possível remover ou variar responsabilidades
facilmente

Solução:
• Crie uma superclasse decoradora (Decorator) que estenda o componente (Component)
que será decorado e que receba como argumento um componente decorado,
• Implemente o método de decoração na classe decoradora de forma a executar o
mesmo método na classe decorada,
• Crie subclasses da decoradora (ConcreteDecorator), sobrecarregando o método de
decoração de forma a chamar o método da classe-mãe e em seguida adicionar novo
comportamento.

Diagramas:
Diagrama de Classes

Client Component

ConcreteComponent Decorator +component

operat ion() op erati on()

operation() {
component.operation()
}

ConcreteDecoratorA
ConcreteDecoratorB
operation()
newOperation() operation()

Conseqüências:
• Permite a construção de diversas combinações e variações de responsabilidades
• A classe componente não precisa ter conhecimento da existência do decorador
• Permite adição de comportamento especial a classes previamente existentes sem
utilização de herança
• Geralmente leva a um sistema com um grande número de classes pequenas, com
poucas funcionalidades específicas.

Padrões Relacionados:
Adapter adiciona funcionalidade a uma classe, porém permite a modificação de sua interface.
Um Decorator pode ser visto como um Composite com um só componente. Strategy permite
modificar o funcionamento dos objetos, enquanto Decorator modifica sua aparência.
Factory Method
Creational Pattern

Objetivo: Definir uma interface para criação de um objeto e deixar que subclasses decidam o
que instanciar.

Solução:
•Crie um Factory Method na classe Creator, com a finalidade de instanciar um objeto
(Product). Este método pode implementar uma funcionalidade padrão ou ser definido como
abstrato.
•Subclasses da classe Creator sobrescrevem o Factory Method e instanciam um produto
específico (SpecificProduct) da maneira desejada (o SpecificProduct deve ser subclasse de
Product).
•Opcionalmente, passe um parâmetro para o Factory Method especificando o tipo de
produto a ser instanciado.

Diagramas:
Diagrama de Classes
AnyOperat ion() {
Creator
...
Product Cl ient Product p = Fact oryMet hod()
FactoryMethod() ...
AnyOperation() }

ConcreteCreator FactoryMethod() {
ConcreteProduct return new ConcreteProduct()
FactoryMethod() }

Consequências:
•Elimina a necessidade de associação a classes específicas (SpecificProducts) na aplicação.
•Conecta hierarquias de objetos paralelas.
•Garante mais flexibilidade na criação de objetos do que o processo convencional de
instanciação.
•Para utilizar-se de um novo tipo de SpecificProduct, o usuários deve criar também uma
nova subclasse criadora (SpecificCreator), aumentando o número de classes do sistema.

Padrões Relacionados:
Abstract Factories geralmente utilizam Factory Methods. Factory Methods são um tipo especial
de Template Methods. Em algumas situações, o padrão Prototype substitui o Factory Method.
Façade
Structural Pattern

Objetivo: Prover uma interface de alto nível para um subsistema complexo e composto de
vários objetos e operações, simplificando seu uso e ocultando detalhes de implementação.

Solução:
• Clientes comunicam-se com o subsistema através dos métodos definidos na fachada
(Facade) – ele não deve acessar os objetos do subsistema diretamente.
• O subsistema geralmente não tem conhecimento da classe cliente ou mantém
referência ao objeto fachada nem do cliente.

Diagramas:
Diagrama de Classes
Facade
Client
operation()

Conseqüências:
• Reduz a complexidade de um subsistema, reduzindo o número de classes que o cliente
necessita utilizar,
• Promove o desacoplamento entre o cliente e o subsistema, permitindo que as classes
do subsistema sejam modificadas sem impactar o sistema cliente,
• Reduz o número de objetos com quem o cliente deve lidar.

Padrões Relacionados:
Facades podem ser substituídas por Mediators em alguns casos. Elas são geralmente
implementadas utilizando-se o padrão Singleton. Podem-se utilizar Abstract Factories quando
se deseja construir um subsistema que necessite de configurações específicas de plataforma
ou varie sua representação interna
Flyweight
Structural Pattern

Objetivo: Utilizar compartilhamento para suportar um grande número de objetos


Interpreter
Behavioral Pattern

Objetivo: Definir uma representação para a gramática de uma linguagem dada e interpretar a
representação de forma a processar sentenças na linguagem
Iterator
Behavioral Pattern

Objetivo: Prover uma via de acesso a conjuntos de objetos agregados sem expor sua
representação
Prototype
Creational Pattern

Objetivo: Especificar o tipo de objeto a ser criado utilizando uma interface protótipo e criar
novos objetos copiando esta instância.

Solução:
•Crie uma classe Product que defina um método abstrato de clonagem.
•Crie subclasses específicas de produtos (SpecificProducts) que implementam o método de
clonagem e retornam uma cópia de si mesmas.
•Durante a inicialização do sistema ou em algum momento adequado, crie uma instância
“protótipo” de cada produto específico (SpecificProduct).
•Sempre que for necessária uma instância de um SpecificProduct, clone o objeto protótipo
utilizando o método de clonagem e utilize o objeto retornado.

Diagramas:
Diagrama de Classes
Client Product
prototype

operation() clone()

operation() { SpecificProduct
Product p = Product.clone()
} clone()

Consequências:
•Permite a escolha de que classe instanciar em tempo de execução.
•Útil quando a duplicação de objetos com informações de estado é mais apropriada do que
um novo processo de instanciação e configuração de estado.
•Reduz ou elimina a necessidade de implementação de hierarquias de Factories paralelas
às hierarquias de Produtos.
Singleton
Creational Pattern

Objetivo: Garantir que uma classe possua apenas uma instância e prover um ponto de acesso
global a ela

Solução:
•Declare construtores protegidos ou privados na classe Singleton.
•Declare um atributo interno à classe Singleton que seja da mesma classe do objeto em
questão.
•Declare um método de acesso estático ao objeto responsável Singleton por inicializá-lo se
este for nulo e retorna-lo ao cliente.
•Declare os demais métodos da classe normalmente.

Diagramas:
Diagrama de Classes
Singleton
Client Sing leton sing le

operation() sta tic getInstance()


sin gletonOperati on()

operation() { static getInstance() {


Singleton s = Singleton.getInstance() return single;
} }

Consequências:
•Garante que somente uma instância da classe será criada
•Controla o acesso à instância do objeto

Padrões Relacionados:
Abstract Factories, Builders e Prototypes podem ser implementadas utilizando-se Singletons.
Em ambientes com múltiplas linhas de execução (Multi-Threading), o padrão Double Checked
Locking é usualmente utilizado. Quando são necessárias várias instâncias controladas de um
objeto, utilize o padrão Multiton.
Mediator
Behavioral Pattern

Objetivo: Define um objeto que encapsula como um conjunto de objetos deve interagir. O
mediador impede que objetos se referenciem explicitamente e permite trocar as interações
entre eles de maneira independente
Memento
Behavioral Pattern

Objetivo: Capturar e externalizar o estado interno de um objeto sem violar encapsulamento,


de forma que o estado possa ser recuperado posteriormente.
Observer
Behavioral Pattern

Objetivo: Definir um relacionamento um-para-muitos entre objetos, de forma que todos os


objetos dependentes são notificados e atualizados automaticamente quando o estado do
objeto observado mudar.

Solução:
• Crie uma interface observadora (Observer) que defina o método de notificação de
atualização,
• Crie uma classe notificadora (Subject) que defina uma estrutura capaz de armazenar
referência a objetos do tipo da classe observadora. Crie métodos para adicionar e
remover observadores à notificadora.
• A cada evento de mudança de estado do notificador, chame o método adequado dos
objetos que tenham se registrado como observadores.

Diagramas:
Diagrama de Classes
n oti fyAl lObse rvers() {
for each observer i n observers {
obs erver.update()
}
}
Subjec t

+obs ervers Observer


add()
remove()
notifyAllObservers() 0..* update()
reques t()

RealSubject RealObserver

request() update()

Conseqüências:
• O objeto notificador tem pouco conhecimento sobre os objetos observadores,
• Objetos podem ser facilmente adicionados ou removidos como receptores de
notificações,
• Notificações de atualização são facilmente propagadas a todos os interessados

Padrões Relacionados:
Mediator pode ser utilizado para controlar ou restringir as notificações.
Proxy
Structural Pattern

Objetivo: prover um procurador para mediar o acesso a outro objeto.

Solução:
• Crie uma classe de conceito abstrata (Subject) que defina a interface pública para
realizar as operações necessárias
• Crie uma subclasse da classe de conceito que implemente realmente as operações da
interface (RealSubject)
• Crie uma subclasse da classe de conceito (Proxy), que será responsável por instanciar a
classe de implementação real e direcionar requisições para ela.

Diagramas:
Diagrama de Classes

request() {
Client S ubje ct realSubject.request()
}

RealSubject +realSubject Pro xy

request() re quest( )

Conseqüências:
• A classe procuradora pode adicionar funcionalidades à classe de objeto acessada por
ela
• Proxies podem ser utilizados para prover representação local a um objeto em outro
espaço (remote proxy), controlar a criação de objetos caros sob demanda (virtual
proxy), proteger acesso ao objeto (protection proxy) ou manter uma referência de forma
a realizar operações adicionais sobre um objeto (smart reference)

Padrões Relacionados:
Adapter tem funcionamento similar ao Proxy, exceto pelo fato de que o Proxy tem interfaces
iguais na classe conceito e no procurador.
State
Behavioral Pattern

Objetivo: Permitir a um objeto alterar seu comportamento quando seu estado interno mudar.

Solução:
• Declare uma classe de estado abstrata que defina a interface de operações que devam
variar de acordo com o estado do sistema
• Crie uma subclasse da classe de estado para cada estado real do sistema
• Mantenha no cliente (contexto) uma referência à classe de estado abstrata
• Sempre que o estado do sistema precisar mudar, faça o cliente instanciar uma
subclasse específica da classe de estado
• Para cada operação dependente de estado, chame o método adequado a partir do
cliente para executar a operação

Conseqüências:
• Objetos de estado podem eliminar a presença de grandes blocos condicionais
• Mudança e dependência de estados se torna visível e explícita
• Estados podem ser utilizados por outros subsistemas, em especial se não mantiverem
dados
Strategy
Behavioral Pattern

Objetivo: Definir e encapsular uma família de algoritmos e torná-los intercambiáveis, de forma


que o cliente pode utilizar qualquer implementação independentemente.

Solução:
• Crie uma classe de estratégia abstrata que defina a interface comum ao algoritmo
• Defina uma subclasse da estratégia para cada implementação do algoritmo e
implemente os métodos definidos na classe abstrata
• Mantenha uma referência à estratégia abstrata na classe cliente (contexto)
• Utilize no cliente a subclasse adequada da estratégia abstrata sempre que necessário

Conseqüências:
• Permite fácil reutilização de famílias de algoritmos ou comportamentos
• Garante mais flexibilidade do que estender a classe cliente para modificar seu
comportamento
• Evita laços condicionais, substituindo-os por implementações concretas da estratégia
• Pode ser utilizado para prover várias implementações de um comportamento similar, de
forma a permitir ajustes de performance
• O cliente pode ter que conhecer especificamente a estratégia que deseja utilizar para
selecioná-la
• A implementação dos algoritmos pode não requerer todos os parâmetros definidos na
estratégia abstrata, gerando overhead desnecessário
Template Method
Behavioral Pattern

Objetivo: Definir o esqueleto de um algorítmo em uma operação e deferir alguns passos para
as subclasses, de forma que as mesmas redefinam alguns passos do algoritmo sem modificar
sua estrutura.

Solução:
• Quebre a seqüência de operações longas em chamadas a métodos separados
(ganchos), na superclasse modelo
• Implemente os métodos-gancho nas subclasses da classe modelo de forma a realizar
operações específicas ou em um ambiente operacional específico

Conseqüências:
• Leva a uma estrutura de controle invertida conhecida como o “princípio de Hollywood”
(“don’t call us, we’ll call you”)
• Delega a implementação de pontos de um processo a subclasses – um conceito
fundamental na construção de frameworks e bibliotecas de classes
Visitor
Behavioral Pattern

Objetivo: Representar uma operação a ser realizada em elementos de uma estrutura de


objetos, de forma a poder definir novas operações sem modificar as classes sobre as quais elas
operam.
Referências Bibliográficas
Gamma, Helm, Vlissides, Johnson. Design Patterns – Elements of Reusable Object Oriented Software.
Addison Wesley, Outubro, 1994.

Você também pode gostar