Design-Patterns - Guia Rapido

28
Guia de consulta rápida Design Patterns Herval Freire de Albuquerque Júnior Versão 0.5

Transcript of Design-Patterns - Guia Rapido

Page 1: Design-Patterns - Guia Rapido

Guia de consulta rápida

Design Patterns

Herval Freire de Albuquerque Júnior

Versão 0.5

Page 2: Design-Patterns - Guia Rapido

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.

Page 3: Design-Patterns - Guia Rapido

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 ProjetoNos 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õesExistem 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õesDe 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:

Page 4: Design-Patterns - Guia Rapido

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õesNo 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.

Page 5: Design-Patterns - Guia Rapido

Abstract FactoryCreational 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

SpecificFactory

FactoryMethodX()FactoryMethodY()

SpecificProduct

SpecificProductY

AbstractFactory

FactoryMethodX()FactoryMethodY()

ProductY

ProductX

Client

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.

Page 6: Design-Patterns - Guia Rapido

AdapterStructural 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)

Adapter

request()

Target

specifi cRequest()

Interface

request()

Client

implementation

request() { specificRequest()}

Diagrama de Classes (utilizando composição)

Interface

request()

Cl ien t

Adapter

request()

Target

specifi cRequest()

+adaptee

request() { adapteee.specificRequest()}

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.

Page 7: Design-Patterns - Guia Rapido

BridgeStructural 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

RefinedAbstraction

ConcreteImplA

operationImpl()

ConcreteImplB

operationImpl()

Implementor

operationImpl()

Abstraction

operation()

+impl

operation() { impl.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.

Page 8: Design-Patterns - Guia Rapido

BuilderCreational 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

SpecificBuilder

BuildPartX()BuildPartY()GetResult()

SpecificProduct

Builder

BuildPartX()BuildPartY()

Director

Build()

para cada objeto obj na estrutura { se obj.type = PartX entao Builder.BuildPartX

se objtype = PartY entao Builder.BuildPartY}

Diagrama de Seqüência

Client Director SpecificBuilder

new SpecificBuilder()

new Director(specificBuilder)

Build() BuildPartX()

BuildPartY()

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 RelacionadosO 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.

Page 9: Design-Patterns - Guia Rapido

Chain of ResponsibilityBehavioral 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.

Page 10: Design-Patterns - Guia Rapido

CommandBehavioral Pattern

Objetivo: Encapsular uma requisição como um objeto, permitindo chamadas com parametrização de diferentes requisições encapsuladas em objetos

Page 11: Design-Patterns - Guia Rapido

CompositeStructural 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

Leaf

operation()

Client

Component

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

Composite

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

+childrenoperation() { for each child in children { 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.

Page 12: Design-Patterns - Guia Rapido

DecoratorStructural 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

ConcreteComponent

operat ion()

Decorator

operation()

Client Component

+component

ConcreteDecoratorA

operation()newOperation()

ConcreteDecoratorB

operation()

operation() { component.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.

Page 13: Design-Patterns - Guia Rapido

Factory MethodCreational 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

ConcreteCreator

FactoryMethod()

ConcreteProduct

AnyOperat ion() { ... Product p = FactoryMethod() ...}

FactoryMethod() { return new ConcreteProduct()}

Creator

FactoryMethod()AnyOperation()

Product Cl ient

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.

Page 14: Design-Patterns - Guia Rapido

FaçadeStructural 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

ClientFacade

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

Page 15: Design-Patterns - Guia Rapido

FlyweightStructural Pattern

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

Page 16: Design-Patterns - Guia Rapido

InterpreterBehavioral 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

Page 17: Design-Patterns - Guia Rapido

IteratorBehavioral Pattern

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

Page 18: Design-Patterns - Guia Rapido

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

SpecificProduct

clone()

Product

clone()

Client

operation()

prototype

operation() { Product p = Product.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.

Page 19: Design-Patterns - Guia Rapido

SingletonCreational 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

operation() { Singleton s = Singleton.getInstance()}

static getInstance() { return single;}

Client

operation()

Singleton

Singleton single

sta tic getInstance()singletonOperation()

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.

Page 20: Design-Patterns - Guia Rapido

MediatorBehavioral 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

Page 21: Design-Patterns - Guia Rapido

MementoBehavioral Pattern

Objetivo: Capturar e externalizar o estado interno de um objeto sem violar encapsulamento, de forma que o estado possa ser recuperado posteriormente.

Page 22: Design-Patterns - Guia Rapido

ObserverBehavioral 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

Observer

update()

Subjec t

add()remove()notifyAllObservers()request()

0..*0..*

+observers

RealSubject

request()

RealObserver

update()

noti fyAl lObservers() { for each observer in observers { obs erver.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.

Page 23: Design-Patterns - Guia Rapido

ProxyStructural 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() { realSubject.request()}

Client Subject

Proxy

request( )

RealSubject

request()

+realSubject

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.

Page 24: Design-Patterns - Guia Rapido

StateBehavioral 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

Page 25: Design-Patterns - Guia Rapido

StrategyBehavioral 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

Page 26: Design-Patterns - Guia Rapido

Template MethodBehavioral 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

Page 27: Design-Patterns - Guia Rapido

VisitorBehavioral 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.

Page 28: Design-Patterns - Guia Rapido

Referências Bibliográficas

Gamma, Helm, Vlissides, Johnson. Design Patterns – Elements of Reusable Object Oriented Software. Addison Wesley, Outubro, 1994.