Padrões de projetos / Design Pattern – Parte 2

Introdução

Conhecer herança, polimorfismo e abstração não o fazem um bom desenvolvedor. Muitas pessoas já passaram pelos mesmos problemas que você está passando ou vai passar e saber utilizar este conhecimento é um início para o caminho das pedras.

Tem gente que pensa que saber fazer if, for, while já é suficiente para se dizer desenvolvedor. É necessário pensar de forma padronizada levando em consideração desempenho, portabilidade, fácil manutenção, fácil compreensão e muitos outros pontos que poderia ser um bom e grande post.

Este post visa iniciar os estudos nos padrões de projetos para obter uma visão geral. Eu sei que escrevo bastante, mas eu tento passar o máximo de informação em menos linhas possíveis. O que acontece é que existe muitas informações a serem passadas… mania de desenvolvedor, hehehehe.

Lembre-se: Um padrão não foi inventado do nada, foi pensado, modelado e utilizado inumeras vezes com resultado de sucesso. Se você estiver tendo problemas com isto, repense, talvez não esteja fazendo da forma correta.

Por onde começar?

Iniciaremos o estudo em cima dos 23 padrões de projetos clássicos do GoF. Não existirá uma sequência definida e sim os mais simples de compreender primeiro.

Abaixo segue a classificação dos 23 padrões segundo o GoF.

Interfaces: Adapter, Facade, Composite, Bridge
Responsabilidade: Singleton, Observer, Mediator, Proxy, Chain Of Responsibility, Flyweight
Construção: Builder, Factory Method, Abstract Factory, Prototype, Memento
Operações: Template Method, State, Strategy, Command, Interpreter
Extensões: Decorator, Interator, Visitor

Veremos, adiante, o que são, como funciona e como implementar estes padrões. Cada um deles resolvem um problema específico, é preciso entender porque, quando e como aplicá-los.

Objetivos dos 23 padrões de projetos

Abaixo veremos, de forma resumida, os objetivos de todos eles, segundo o GoF.

1. Adapter: Converter a interface de uma classe em outra interface esperada pelos clientes.

2. Façade: Oferecer uma interface única de nível mais elevado para um conjunto de interfaces de um subsistema.

3. Composite: Permitir o tratamento de objetos individuais e composições desses objetos de maneira uniforme.

4. Bridge: Desacoplar uma abstração de sua implementação para que os dois possam variar independentemente.

5. Singleton: Garantir que uma classe só tenha uma única instância, e prover um ponto de acesso global a ela.

6. Observer: Definir uma dependência um-para-muitos entre objetos para que quando um objeto mudar de estado, os seus dependentes sejam notificados e atualizados automaticamente.

7. Mediator: Definir um objeto que encapsula a forma como um conjunto de objetos interagem.

8. Proxy: Prover um substituto ou ponto através do qual um objeto
possa controlar o acesso a outro.

9. Chain of Responsibility: Compor objetos em cascata para, através dela, delegar uma requisição até que um objeto a sirva.

10. Flyweight: Usar compartilhamento para suportar eficientemente grandes quantidades de objetos complexos.

11. Builder: Separar a construção de objeto complexo da representação para criar representações diferentes com mesmo processo.

12. Factory Method: Definir uma interface para criar um objeto mas deixar que subclasses decidam que classe instanciar.

13. Abstract Factory: Prover interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.

14. Prototype: Especificar tipos a criar usando uma instância como protótipo e criar novos objetos ao copiar este protótipo.

15. Memento: Externalizar o estado interno de um objeto para que o objeto possa ter esse estado restaurado posteriormente.

16. Template Method: Definir o esqueleto de um algoritmo dentro de uma operação, deixando alguns passos a serem preenchidos pelas subclasses.

17. State: Permitir a um objeto alterar o seu comportamento quanto o seu estado interno mudar.

18. Strategy: Definir uma família de algoritmos, encapsular cada um, e fazê-los intercambiáveis.

19. Command: Encapsular requisição como objeto, para clientes parametrizarem diferentes requisições, filas, e suportar operações reversíveis.

20. Interpreter: Dada uma linguagem, definir uma representação para sua gramática junto com um interpretador.

21. Decorator: Anexar responsabilidades adicionais a um objeto dinamicamente.

22. Iterator: Prover uma maneira de acessar elementos de um objeto agregado seqüencialmente sem expor sua representação interna.

23. Visitor: Representar uma operação a ser realizada sobre os elementos de uma estrutura de objetos.

Soluções para problemas comuns que os padrões de projeto evitam

Especificação explicita de classe na criação de objetos: O sistema está preso a uma implementação específica.
Solução: criar objetos indiretamente com Abstract Factory, Factory Method ou Prototype.

Dependência em operações específicas: O sistema só tem uma forma de satisfazer uma requisição.
Solução: evitar ações “hard-coded” com Chain of Responsibility ou Command.

Dependência em plataforma de hardware ou software: O software precisa ser portado a outras plataformas.
Solução: limitar dependências com Abstract Factory ou Bridge.

Dependência em representações ou implementações de objetos: Clientes que sabem como um objeto é implementado, representado ou armazenado podem precisar serem alterados se o objeto mudar.
Solução: isolar cliente com Abstract Factory, Bridge, Memento ou Proxy.

Dependências de algoritmo: Mudanças de algoritmo são freqüentes. Objetos que dependem de um algoritmo precisam mudar quando o algoritmo mudar.
Solução: isolá-los com Builder, Iterator, Strategy, Template Method ou Visitor

Forte acoplamento: Classes fortemente acopladas são difíceis de reusar, testar, manter, etc.
Solução: enfraquecer o acoplamento com Abstract Factory, Bridge, Chain of Responsibility, Command, Façade, Mediator ou Observer.

Extensão de funcionalidade através de subclasses: Herança é difícil de usar na sua forma correta e a composição dificulta compreensão.
Solução: usar padrões que implementam bem herança e composição como Bridge, Chain of Responsibility, Composite, Decorator, Observer ou Strategy.

Incapacidade de alterar classes convenientemente: Classes inaccessíveis, incompreensíveis ou difíceis de alterar.
Solução: usar Adapter, Decorator ou Visitor.

Tipos de software

Vamos entender as prioridades de padrões de projetos nos tipos comuns de softwares.

Aplicações: Softwares especialistas de modo geral.
Prioridades: reuso interno, manutenção e extensão.

Toolkits, APIs, bibliotecas: Conjunto de classes reutilizáveis de propósito geral. Não impõem design.
Prioridade: amplo reuso de código.

Frameworks: Dita a arquitetura da aplicação. Requer que usuário aprenda o framework e inclua código e configuração.
Prioridade: amplo reuso de design.
Geralmente são fortemente baseados em padrões. Quem conheçe os padrões entende o framework mais facilmente.

Conclusão

O caminho inicial é grande, eu sei, mas é necessário iniciar de algum lugar. Existem padrões de projeto sendo criados o tempo todo, é necessário entender os clássicos antes de se aventurar nos mais novos.

Existem muitos problemas já resolvidos, não vale a pena perder tempo inventando uma forma “rápida” de resolver, vamos usar o conhecimento dos mais experientes. ;)

Referência

Erich Gamma et al. Design Patterns: Elements of Reusable
Object-oriented Software. Addison-Wesley, 1995.

METSKER, Steven John. Design Patterns Java Workbook. Addison-Wesley, 2002.

 

Abraços a todos e até a próxima.

A maioria das pessoas tem êxito porque se determinou a tê-lo. Gente medíocre às vezes consegue um sucesso notável simplesmente porque não sabe quando parar.” George Allen, treinador de futebol americado.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Sair / Alterar )

Imagem do Twitter

You are commenting using your Twitter account. Sair / Alterar )

Foto do Facebook

You are commenting using your Facebook account. Sair / Alterar )

Connecting to %s

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.