Aula 21 e 22

Padrão OBSERVER

Aplicação dos Design Patterns de forma simplificada!

O padrão Observer, é utilizado para quando você precisa encapsular objetos que você não conhece, dentro de um outro e notificá-los após uma determinada ação.

Pré-Requisitos:

Entendimento de orientação à objetos;
Capacidade de abstração;


Situações

Você precisa de um log de ações no seu sistema administrativo;
Você precisa saber quando alguém executou os comandos do seu WebService;
Quando um visitante do seu site fizer cadastro, deve inicializar todas as tabelas relacionadas;


Motivações

Tradicionalmente, aconselha-se o uso de padrões de projeto, pois são uma maneira unificada de falar de um determinado algoritmo;

Segundo estudos, é um padrão com nível máximo de uso;
O .NET Framework utiliza em seus componentes;

Encapsulamento e entendimento simples e fácil;
Utilização correta da orientação à objetos;

Para utilizar o padrão observer, você deve pensar que um objeto, que chamarei de "Subject", irá executar uma ação que outros deverão capturar, que chamarei de "Observer". Veja a demonstração na UML abaixo:



Quando usar o padrão Observer?

Quando uma abstração tem dois aspectos, um dependente do outro. Encapsular tais aspectos em objetos separados permite que variem e sejam reusados separadamente
Quando uma mudança a um objeto requer mudanças a outros e você não sabe quantos outros objetos devem mudar
Quando um objeto deve ser capaz de avisar outros sem fazer suposições sobre quem são os objetos.
Em outras palavras, sem criar um acoplamento forte entre os objetos.


Link Referência

Aula 20

Padrão Singleton

1) Singleton, é um padrão de projeto de software (do inglês Design Pattern). Este padrão garante a existência de apenas uma instância de uma classe, mantendo um ponto global de acesso ao seu objeto.

2) Singleton é um design pattern (padrão de projeto) que tem o objetivo garantir que existe apenas uma instancia de uma certa classe a qualquer instante e em qualquer ponto de um sistema.

Um singleton é um objeto e como tal é o encapsulamento de dados e comportamento. Não é possivel substituir singleton por nenhum outro padrão de projeto. Mas talvez você não esteja precisando de um objeto único e sim de uma forma global de acessar a ele ou uma forma de garantir que só é instanciado uma única vez.

Muitos projetos necessitam que algumas classes tenham apenas uma instância. Por exemplo, em uma aplicação que precisa de uma infraestrutura de log de dados, pode-se implementar uma classe no padrão singleton. Desta forma existe apenas um objeto responsável pelo log em toda a aplicação que é acessível unicamente através da classe singleton.

Exemplo:

public class SingleSpoon
{
private Soup soupLastUsedWith;

private static SingleSpoon theSpoon;
private static boolean theSpoonIsAvailable = true;

private SingleSpoon() {}

public static SingleSpoon getTheSpoon() {
if (theSpoonIsAvailable) {
if (theSpoon == null) {
theSpoon = new SingleSpoon();
}
theSpoonIsAvailable = false;
return theSpoon;
} else {
return null;
//spoon not available,
// could throw error or return null (as shown)
}
}

public String toString() {
return "Behold the glorious single spoon!";
}

public static void returnTheSpoon() {
theSpoon.cleanSpoon();
theSpoonIsAvailable = true;
}

public Soup getSoupLastUsedWith() {
return this.soupLastUsedWith;
}
public void setSoupLastUsedWith(Soup soup) {
this.soupLastUsedWith = soup;
}

public void cleanSpoon() {
this.setSoupLastUsedWith(null);
}
}

class TestSingleSpoon {

public static void main(String[] args) {
System.out.println("First person getting the spoon");
SingleSpoon spoonForFirstPerson =
SingleSpoon.getTheSpoon();
if (spoonForFirstPerson != null)
System.out.println(spoonForFirstPerson);
else
System.out.println("No spoon was available");

System.out.println("");

System.out.println("Second person getting a spoon");
SingleSpoon spoonForSecondPerson = SingleSpoon.getTheSpoon();
if (spoonForSecondPerson != null)
System.out.println(spoonForSecondPerson);
else
System.out.println("No spoon was available");

System.out.println("");

System.out.println("First person returning the spoon");
spoonForFirstPerson.returnTheSpoon();
spoonForFirstPerson = null;
System.out.println("The spoon was returned");

System.out.println("");

System.out.println("Second person getting a spoon");
spoonForSecondPerson = SingleSpoon.getTheSpoon();
if (spoonForSecondPerson != null)
System.out.println(spoonForSecondPerson);
else
System.out.println("No spoon was available");
}
}

Link Referência

Aula 19

Padrão ADAPTER

A função do Padrão ADAPTER é fazer com que a interface de uma classe possa ser "adaptada" à interface de uma outra para que essas possam trabalhar juntas. É a melhor forma de se ligar classes que tenham interfaces imcompatíveis. Podemos usar o Adapter caso seja necessário modificar a interface de uma classe em função de um novo requisito.

O padrão de projeto Adapter é necessário quando possuímos dois objetos que precisam se comunicar mas as suas interfaces são diferentes. O adaptador é responsável por "converter" uma interface em outra tornando possível a comunicação entre os objetos.

EXEMPLO:

public void TomadaTresPinos {
public void fornecerEnergia ();
}

public interface TomadaDoisPinos {
public void fornecerEnergia ();
}

public interface PlugueTresPinos {
public void conectar (TomadaTresPinos tomada) ;
}


public void PlugueDoisPinos {
public void conectar (TomadaDoisPinos) ;
}


public class TomadaEuropeia implements TomadaTresPinos {
public void fornecerEnergia() {

System.out.println("[TOMADA] Fornecendo energia para um plugue de três pinos!");
}

}

public class PlugueEuropeu implements PlugueTresPinos {
public void conectar(TomadaTresPinos tomada) {
System.out.println("[PLUGUE] Pegando energia elétrica de uma tomada de três pinos.");
tomada.fornecerEnergia();
}

}

public class PlugueComum implements PlugueDoisPinos {
public void conectar(TomadaDoisPinos tomada) {

System.out.println("[PLUGUE] Pegando energia elétrica de uma tomada de dois pinos.");
tomada.fornecerEnergia();
}

}

public class Adaptador implements TomadaTresPinos {

private TomadaDoisPinos tomada;

public Adaptador(TomadaDoisPinos tomada) {
this.tomada = tomada;
}

public void fornecerEnergia() {
tomada.fornecerEnergia();
}


}

public class Main {

public static void main(String[] args) {
TomadaDoisPinos tomada = new TomadaComum();
PlugueTresPinos plugue = new PlugueEuropeu();

Adaptador adapter = new Adaptador(tomada);
plugue.conectar(adapter);
}

}



Link Referência

...::: Padrões GOF :::...

História

O conceito de padrão de projeto foi criado na década de 70 pelo arquiteto Christopher Alexander . Em seus livros Notes on the Synthesis of Form, The Timeless Way of Building e A Pattern Language.

Além da definição das características de um padrão, Alexander definiu o formato que a descrição de um padrão deve ter. Ele estabeleceu que um padrão deve ser descrito em cinco partes:

Nome: uma descrição da solução, mais do que do problema ou do contexto.

Exemplo: uma ou mais figuras, diagramas ou descrições que ilustrem um protótipo de aplicação.

Contexto: a descrição das situações sob as quais o padrão se aplica.

Problema: uma descrição das forças e restrições envolvidos e como elas interagem.

Solução: relacionamentos estáticos e regras dinâmicas descrevendo
como construir artefatos de acordo com o padrão, freqüentemente citando
variações e formas de ajustar a solução segundo as circunstâncias.
Inclui referências a outras soluções e o relacionamento com outros
padrões de nível mais baixo ou mais alto.

O movimento ao redor de padrões de projeto ganhou popularidade com o livro Design Patterns: Elements of Reusable Object-Oriented Software , publicado em 1995 .
Os autores desse livro são Erich Gamma , Richard Helm , Ralph Johnson e John Vlissides , conhecidos como a "Gangue dos Quatro" (Gang of Four) ou simplesmente
"GoF". Posteriormente, vários outros livros do estilo foram publicados, como Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development.

Introdução:

Os padrões de projeto de software ou padrões de desenho de software , também muito conhecido pelo termo original em inglês : Design Patterns , descrevem soluções para problemas recorrentes no desenvolvimento de sistemas de software orientados a objetos.

Um padrão de projeto estabelece um nome e define o problema, a solução, quando aplicar esta solução e suas conseqüências.

Os padrões de projeto visam facilitar a reutilização de soluções de desenho - isto é, soluções na fase de projeto do software, sem considerar reutilização de código. Também acarretam um vocabulário comum de desenho, facilitando comunicação, documentação e aprendizado dos sistemas de software.


...::: Padrões GOF :::...

Os padrões "GoF" são organizados em famílias de padrões: de criação, estruturais e comportamentais. Os padrões de criação são relacionados à criação de objetos, os estruturais tratam das associações entre classes e objetos e os comportamentais das interações e divisões de responsabilidades entre as classes ou objetos.


Um padrão "GoF" também é classificado segundo o seu escopo; de classe ou de objeto. Nos padrões com escopo de classe os relacionamentos que definem este padrão são definidos através de herança e em tempo de compilação . Nos padrões com escopo de objeto o padrão é encontrado no relacionamento entre os objetos definidos em tempo de execução.

Aula 14

Padrão Controller

Model-view-controller (MVC) é um padrão de arquitetura de software. Com o aumento da complexidade das aplicações desenvolvidas torna-se fundamental a separação entre os dados (Model) e o layout (View). Desta forma, alterações feitas no layout não afectam a manipulação de dados, e estes poderão ser reorganizados sem alterar o layout.

O model-view-controller resolve este problema através da separação das tarefas de acesso aos dados e lógica de negócio, lógica de apresentação e de interacção com o utilizador, introduzindo um componente entre os dois: o Controller. MVC é usado em padrões de projeto de software, mas MVC abrange mais da arquitetura de uma aplicação do que é típico para um padrão de projeto.

Lida com o tratamento de mensagens ou eventos de sistema.

Atribuir a responsabilidade de tratar eventos do sistema a uma classe que representeuma das seguintes opções:

▪Representa o sistema como um todo, um dispositivo ou um subsistema (umcontrolador fachada);
▪Representa um caso de uso em que o evento de sistema ocorre (controlador de casode uso ou sessão).

A arquitetura MVC - (Modelo Visualização Controle) fornece uma maneira de dividir a funcionalidade envolvida na manutenção e apresentação dos dados de uma aplicação.
A arquitetura MVC não é nova e foi originalmente desenvolvida para mapear as tarefas tradicionais de entrada , processamento e saída para o modelo de interação com o usuário.
Usando o padrão MVC fica fácil mapear esses conceitos no domínio de aplicações Web multicamadas.

Na arquitetura MVC o modelo representa os dados da aplicação e as regras do negócio que governam o acesso e a modificação dos dados.
O modelo mantém o estado persistente do negócio e fornece ao controlador a capacidade de acessar as funcionalidades da aplicação encapsuladas pelo próprio modelo.

Vantagens do modelo MVC :

Como o modelo MVC gerencia múltiplos visualizadores usando o mesmo modelo é fácil manter , testar e atualizar sistemas múltiplos
É muito simples incluir novos clientes apenas incluindo seus visualizadores e controles
Torna a aplicação escalável
É possível ter desenvolvimento em paralelo para o modelo , visualizador e controle pois são independentes.

Desvantangens do modelo MVC:

Requer uma quantidade maior de tempo para analizar e modelar o sistema
Requer pessoal especializado
Não é aconselhável para pequenas aplicações

Aulas 11, 12 e 13

Acoplamento de Controle

Um controlador é um objeto responsável por tratar um evento de sistema (caso de uso), mas que pertence à camada de domínio.

Problema:
Que objeto, fora da camada de apresentação, deve receber e coordenar a solicitação da execução de uma operação?

Solução:
Uma classe que representa uma das seguintes opções:

– Representa o ”sistema”, todo o negócio ou organização (Controlador fachada);
– Representa todo o negócio e
– Representa algo do mundo real que é ativo e envolvido na tarefa (Controlador de papel);
– Representa um “tratador artificial” dos eventos de sistema de um caso de uso (Controlador de caso de uso)

O controlador é o primeiro objeto fora da camada de interface com o usuário a receber ou tratar uma mensagem para o sistema.

Existem duas alternativas possíveis para o objeto controlador:

- Um objeto Controlador para todo o sistema
- Um objeto Controlador por Caso de Uso

Os benefícios do padrão controlador são:
--- Diminui a sensibilidade da camada de apresentação em relação à lógica de domínio
--- Oportunidade para controlar o estado do caso de uso.

» Evita que objetos da camada apresentação tratem as operações do sistema;
» Aumenta o potencial de reutilização;
» Possibilita o controle de seqüência de operações do sistema.

Aula 9 e 10

Padrão Baixo Acoplamento:


O padrão baixo acomplamento tem como objetivo a redução e miniminização da conexão de um objeto com outros. Esta conexão esta relacionada a ter conhecimento sobre os outros objetos ou simplemente depender de outros objetos. De forma sujacente manter o acoplamento baixo significa redizir o impacto de mudança já que ao se alterar um objeto um mínimo de outros objetos serão afetados.

Problema: Como aumentar independência dos objetos de forma a possibilitar a sua reutilização?

Solução: Atribuindo responsabilidades de maneira que o acoplamento permaneça fraco.


Resulta num acoplamento geral mais fraco entre as classes:

»Resulta em classes mais independentes;
»Reduz o impacto de mudanças;
»Aumenta o potencial de reutilização;
»Não deve ser utilizado isolado dos outros padrões.

Aula 8


public class Produto
{
private integer idProduto;
private string descrição;
private double valorUnitário;

public string getdescrição(){
return dscrição;
} public void setDescrição(string valor)
{ descrição=valor;
}

public class ItemVenda {
private double qtde;
private Produto p;

public void setP (Produto p) {
this.p = p;
}

public class Venda {
private Set itemVendaLiat=new HashSet();
private Date dataVenda;
private integer idvenda;
public criar Itemvenda (Produto P, double qtde)
{
Itemvenda i =new ItemVenda();
i.setP(p);
i.setQtde(qtde);
itemVendaList.add(i);
}

Atribui à classe "A" a responsabilidade de instanciar a classe B caso algumas destas condições sejam verdadeiras (quanto mais alternativas sejam verdadeiras melhor).

Aula 7

Padrão Criador

Problema: Quem deveria ser responsável pela criação de uma nova instância de classe?

Solução: Atribuir à classe B a responsabilidade de criar uma instância da classe A se uma das seguintes condições for verdadeira:

– B agrega objetos A;
– B contém objetos A;
– B registra instâncias de objetos A;
– B usa de maneira muito próxima objetos A;
– B tem os dados de inicialização de A (B é expert em
relação à criação de A.

Acoplamento
O acoplamento é uma medida de quão fortemente uma classe está conectada a outras classes, tem conhecimento das mesmas ou depende delas.

Problema: Como aumentar independência dos objetos de forma a possibilitar a sua reutilização?

Solução: Atribuindo responsabilidades de maneira que o acoplamento permaneça fraco.

Alta Coesão

Coesão é a medida de quão fortemente relacionadas e focalizadas são as responsabilidades de uma classe.

Problema: Como manter a complexidade de um sistema ou objeto sob controle?

Solução: Atribuindo responsabilidades de maneira que a coesão permaneça alta.


Acoplamento fraco e coesão alta são princípios a serem seguidos durante todas as decisões de projeto; são objetivos adjacentes a serem levados em conta continuamente.

Uma classe com coesão baixa faz muitas coisas não relacionadas, ou executa demasiado trabalho.

»Coesão funcional alta especialização das classes;
»Uma classe com Coesão alta tem um número relativamente pequeno de métodos, com funcionalidades altamente relacionadas;
»A manutenção e as melhorias do sistema são facilitadas;
»Reduz o impacto de mudanças;
»Aumenta o potencial de reutilização;
»Não deve ser utilizado isolado dos outros padrões.

Aula 6

Aula realizada em Laboratório.

Aula 5

Um sistema O.O. é composto por vários objetos que colaboram entre si, trocando "mensagens" para satisfazer aos requisitos do sistema proposto, o planejamento de como dividir as responsabilidades entre os objetos é essencial para obter um sistema fácil de entender, robusto, reutilizável e extensível.

GRASP: ajuda a definir as responsabilidades, o seu estudo possibilita entender os princípios de um bom projeto O.O.

Responsabilidades: São as descrições do que os objetos tem de fazer, os métodos são as implementações das responsabilidades.
Obs: nem sempre uma responsabilidade é satisfeita somente por um método, grandes responsabilidades são divididas para manter a coesão da Classe.


Os principais padrões GRASP:

- Especialista
- Criador
- Coesão alta
- Acoplamento fraco
- Controlador


Especialista na Informação:

Problema: Qual é o princípio geral para a atribuição de responsabilidades aos objetos?

Solução: Atribua a responsabilidade ao especialista: a classe que tem as informações necessárias para assumir a responsabilidade.

Benefícios: O encapsulamento da informação é mantido uma vez que os objetos usam seus próprios dados para realizar as tarefas.

Isto normalmente leva a um baixo acoplamento entre as classes.

O comportamento do sistema é distribuído entre as classes que têm as informações, encorajando a definição de classes mais "leves", mais fáceis de entender e de manter.

Contradição: Em algumas situações, a solução sugerida pelo especialista pode ser indesejada, por às vezes causar baixa coesão.

Aula 4

Padrões GRASP - (General Responsibility Assignment Software Patterns)
Os padrões GRASP fornecem uma abordagem sistemática para a atribuição de responsabilidades às classes do projeto.

As responsabilidades estão relacionadas às obrigações de um objeto em termos do seu comportamento.
Elas são de dois tipos:
-- Conhecer
-- Fazer

As responsabilidades de fazer de um objeto incluem:
- Fazer algo ele próprio
- Iniciar ações em outros objetos
- Controlar e coordenar atividades em outros objetos

As responsabilidades do conhecer de um objeto incluem:
- Conhecer dados privados encapsulados
- Conhecer objetos relacionados
- Conhecer coisas que ele pode derivar ou calcular

Exemplos:
• Uma Venda tem a responsabilidade de criar linha de detalhe (fazer algo).
• Uma Venda tem a responsabilidade de saber sua data (conhecer algo).

Granularidade

Uma responsabilidade pode envolver um único método (ou poucos).
Exemplo: Criar uma linha de detalhe.

Uma reponsabilidade pode envolver dezenas de classes e métodos.
Exemplo: Responsabilidade de fornecer acesso a um BD.

Uma responsabilidade não é igual a um método.
Mas métodos são usados para implementar responsabilidades.

Uma responsabilidade não é a mesma coisa que um método.
Os métodos são implementados para satisfazer responsabilidades.

As responsabilidades são implementadas usando métodos que agem sozinhos ou colaboram com outros métodos e objetos.

Referências:
LINK 1
LINK 2

Aula 3

Diagrama de Sequência:
O diagrama de seqüência dá ênfase à ordenação temporal das mensagens e as principais características que o diferencia do diagrama de colaboração são: possui linha de vida do objeto que é uma linha tracejada que representa a existência de um objeto em um período de tempo e também existe o foco de controle que é um retângulo alto e estreito que mostra o período durante o qual o objeto está desempenhando uma ação, diretamente ou por meio de um procedimento subordinado, enquanto que o diagrama de colaboração possui um caminho para identificar se o objeto é global, local etc e possui também um número de seqüência que indica a ordem temporal de uma mensagem.
Exemplo:



Diagrama de Colaboração:
O diagrama de colaboração dá ênfase à organização estrutural dos objetos que enviam a recebem mensagens. O diagrama de colaboração é formado colocando-se primeiro os objetos que participam da interação como os vértices de um gráfico, depois, representa-se os vínculos que conectam esses objetos como os arcos dos gráficos e finalmente, adorna-se esses vínculos com as mensagens que os objetos enviam e recebem.
Exemplo:


Obs: Os diagramas de seqüência e colaboração são semanticamente equivalentes, sendo assim, o diagrama de uma forma pode ser convertido no outro sem qualquer perda de informação, entretanto, isso não significa que os dois diagramas visualizarão as mesmas informações explicitamente.

Link Referência Bibliográfica

Aula 1 e 2


Projeto Orientado a Objeto:
Objetivo: Projetar sistemas usando objetos auto-contidos e classes de objetos.

Análise vs Projeto

Análise: é modelar um problema, é uma atividade de investigação. "O que deve ser feito", ou seja, entender.

Projeto: é a modelagem da solução, se dedica a desenvolver um modelo orientado a objeto de um sistema de software para implementar os requisitos.

Durante a Análise OO, a ênfase está em achar e descrever objetos (ou conceitos) no domínio do problema.

Durante o Projeto orientado a objeto, a ênfase está em achar objetos lógicos de software que poderão ser eventualmente implementados usando uma linguagem de programação OO. Esses objetos podem ter atributos ou métodos.


Continua....