PADRÕES DE PROJETO. GoF(Gang of Four) GRASP (General Responsibility Assignment Software Patterns). PRINCÍPIOS DE PADRÕES DE PROJETO. Princípio Aberto Fechado Entidades de software como classes, módulos e funções devem ser abertas para expansão, mas fechadas para modificações Princípio Inversão de Dependência • “Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações.”; • “Abstrações não deve depender de detalhes. Detalhes devem depender abstrações”. Princípio Segregação de Interfaces “Os clientes não devem depender de interfaces que eles não usam”. Este princípio nos ensina a cuidar da forma que escrevemos nossas interfaces. Quando escrevemos as nossas interfaces, deve-se ter o cuidado de só acrescentar métodos que deveriam estar lá. Se acrescentamos métodos que não deveriam estar lá as classes que à implementam terão que implementar esses métodos. Por exemplo, se vamos criar uma interface chamada Trabalho e adicionar um método de intervalo para o almoço, todos os trabalhadores terão de implementá-lo. E se o trabalhador é um robô? Interfaces contendo métodos que não são específicas para isso são chamadas poluídas ou de gorduras interfaces. Devemos evitá-los. Programe para uma interface, e não para uma implementação. Desta forma, você encapsula os códigos que podem variar para que futuras alterações não sejam complicadas e também forneça um único ponto de alteração. Esse princípio é a base de todos os padrões. O padrão strategy a utiliza. Dê preferência para o “Tem um” à “é um”. “Dar prioridade e composição”. Padrões de projeto tendem a dar prioridade a utilização de composição, ela permite o controle dos objetos em “tempo de execução”, dinamicamente, enquanto heranças são estáticas e pouco flexíveis(“em tempo de compilação”) Lembre-se que composição é um tipo de associação(“UML”) bidirecional entre objetos instanciados, daí a manipulação ser em tempo de execução. Encapsule o que varia Programe para interface à implementação. Dessa forma seu código estará preparado para o futuro de forma mais flexível e extensível. Padrões de criação Abstract Factory Builder Factory Method Prototype Singleton Abstract Factory Fornece uma interface para a criação de uma família de objetos relacionados ou dependentes, sem especificar suas classes concretas. Também é conhecida como “KIT”. Como possui escopo de objeto, manipula objetos em “tempo de execução(composição)” fornece interfaces para serem implementadas por classes que desejam criar seus objetos. Builder Permite a separação da construção de um objeto complexo da sua representação, de forma que o mesmo processo de construção possa criar diferentes representações. Um exemplo é a conversão em “tempo de execução” do um formato RTF. Se diferencia do Abstract Factory pela criação de objetos passo a passo, ao invés de criar todos os objetos de uma só vez. Factory Método(Fabrica Virtual) Define uma interface para a criação de um objeto, mas deixa as subclasses decidirem qual classe a ser instanciada. permite postergar(deferir) a instanciação em subclasses. Em resumo, deixa as subclasses escolherem quais objetos criarem(através de herança). Esse padrão é o único voltado para o escopo classe, os demais são voltados para objeto. Lembrando que os escopo de classe são manipulados em “tempo de compilação(herança)” e os de objetos, em “tempo de execução(composição e delegação)”. Prototype Especifica objetos a serem criados usando uma instância-protótipo e cria(clona) uma cópia a partir desse protótipo. Possui escopo de objeto, então, adiciona ou remove objetos em “tempo de execução” Singleton Garante que uma classe tenha somente uma instância e fornece um ponto global de acesso a mesma. Termos estudados • Escopo • Princípios • Aberto/fechado, preferir composição, Dependência, programe para interfaces e encapsule o que varia. • Orientação •Padrões de criação •Abstract Factory, builder, factory method, prototype e singleton. Padrões estruturais Adapter Bridge Composite Decorator Façade Flyweight Proxy Adapter(Wrapper) Converte interface de uma classe em outra interface, esperada pelo cliente. O Adapter permite que interfaces incompativeis trabalhem em conjunto. OBS: O adapter é o único padrão estrutural que trabalha com o ambos os escopos(Classe e objeto) Bridge(Handle/body) Desacopla a abstração de sua implementação, de modo que as duas possam variar independentemente. Exemplo: Criar uma aplicação que funcione no windows e no linux. É indicado quando podemos ter várias implementações possíveis para uma abstração e vc deseja evitar o vínculo entre a abstração e sua da implementação. Composite Compor os objetos em uma estrutura de árvore para representar uma hierarquia parte/todo. Exemplo: Aplicações gráficas que agrupam objetos simples para a partir daí formarem estruturas complexas(Paletas do photoshop ou do MS visio.) Decorator(Wripper) Dinamicamente, adiciona nova responsabilidade a objetos Facede Fornece uma interface unificada para um conjunto de interfaces de um subsistema. * É aplicável quando queremos fornecer uma única interface para um subsistema complexo. * Estruturar subsistemas em camadas. * Reduzir o acoplamento entre clientes e subsistemas. Flyweight A intenção é usar o compartilhamento para suportar uma grande quantidade de objetos de granularidade fina. Use o Flyweight quando a quantidade de objetos foi muito grande. Proxy Fornece um substituto(surrogate) ou um marcador da localização de um objeto para controlar o acesso a esse objeto. Exemplo: quando abrimos o word uma foto que exista na página 2 não precisará ser carregada se nós só precisarmos visualizar a pagina 1. A função do proxy é controlar a criação de objetos no momento que realmente é necessário. Padrões de comportamento Chain of Responsibility Command Interpreter Iterator Mediator Memento Observer State Strategy Template Method Visitor Chain of Responsibility Evita o acoplamento do remetente de uma solicitação ao seu receptor, ao dar a mais de um objeto a oportunidade de tratar a solicitação.Encadear os objetos receptores, passando a solicitação ao longo da cadeia até que algum objeto a trate. A Idéia desse padrão é desacoplar o remetente e receptor, dando a oportunidade a múltiplos objetos para tratar a solicitação. Command(Action ou transaction) Encapsular uma solicitação como um objeto, desta forma permitindo que clientes parametrizem diferentes solicitações, enfileirem ou façam o registro (log) de solicitações e suportem operações que podem ser desfeitas. Interpreter Dada uma linguagem, defina uma representação para sua gramática. Iterator(Cursor) Fornece uma maneira de acessar seqüencialmente os elementos de um objeto. Mediator Define um objeto que encapsula como um conjunto de objetos interage. Ao invés de cada os objetos se comunicarem entre sí, se comunicam com o mediator (Mediador) de forma centralizada, isso diminui o acoplamento de muitos objetos entre sí. Compare-o como um switch. Melhor exemplo é o DNS. Memento(Token) Sem violar o encapsulamento,captura e externaliza o estado interno de um objeto de modo que ele possa ser restaurado posteriormente. Pense no memento como, como o recurso de salvar o estágio de um jogo para ser restaurado depois. Ele faz um snapshot do objeto. Interessante quando queremos implementar recursos de checkpoint e rollback. Observer (Dependents, Publish-Subscribe) Define uma dependência um-para-muitos entre objetos, de modo que, quando um objeto muda de estado, todos os seus dependentes sejam atualizados. State Permite a alteração do comportamento de um objeto quando seu estado interno é modificado. Strategy(Policy) Define uma família de algoritmos, encapsula cada um deles para torná-los intercambiáveis, esse padrão permite que o algoritmo varie independente dos clientes que a utilizem. Lembre-se do princípio: “encapsular o que varia”. Template method Define um esqueleto de um algoritmo em uma operação, postergando a operação de alguns passos para subclasses. Esse padrão permite que subclasses redefinam alguns passos sem mudar sua estrutura. Exemplo: em um algoritmo para fazer chá ou café teríamos o esqueleto de todos os passos comuns para fazer café e chá, deixando para subclasses apenas os passos “Adicione pó de café”, para a subclasse que implemente fazer café, e “Adicione pó de chá”, para a subclasse que implementa fazer chá. É boa prática usar a função “final” do java para evitar que o algoritmo seja alterado por subclasses. Visitor Representa uma operação a ser executada sobre os elementos da estrutura de um objeto. Permite definir uma nova operação sem mudar as classes dos elementos sobre os quais opera. DIVISÃO Novos princípios • Dependa de abstrações não de classes concretas. • Princípio do conhecimento mínimo: “Só fale com seus amigos mais próximos”, Lembre-se do “facade” e do “mediator” • Princípio Hollywood:”Não nos ligue, nós ligamos pra vc”. Ele evita o colapso de dependências. Faz com que módulos de alto nível controlem quando módulos de baixo nível serão chamados. Ex: Template method, Factory method, Observer.