quinta-feira, 8 de maio de 2008

AULA 23 e 24 - PADRÃO COMMAND


Command é um dos 23 padrões de projeto do GOF e é um dos 11 padrões comportamentais


Encapsular uma solicitação como um objeto, desta forma permitindo parametrizar clientes com diferentes solicitações, enfileirar ou fazer o registro (log) de solicitações e suportar operações que podem ser desfeitas.


Algumas vezes é necessário emitir solicitações para objetos nada sabendo sobre a operação que está sendo solicitada ou sobre o receptor da mesma.
Utilizar quando:
Parametrizar objetos por uma ação a ser executada. Você pode expressar tal parametrização numa linguagem procedural através de uma função callback, ou seja, uma função que é registrada em algum lugar para ser chamada em um momento mais adiante. Os Commands são uma substituição orientada a objetos para callbacks;
Especificar, enfileirar e executar solicitações em tempos diferentes. Um objeto Command pode ter um tempo de vida independente da solicitação original. Se o receptor de uma solicitação pode ser representado de uma maneira independente do espaço de endereçamento, então você pode transferir um objeto Command para a solicitação para um processo diferente e lá atender a solicitação;
Suportar desfazer operações. A operação Execute, de Command, pode armazenar estados para reverter seus efeitos no próprio comando. A interface do Command deve ter acrescentada uma operação Unexecute, que o reverte.efeitos de uma chamada anterior de Execute. Os comandos executados são armazenados em uma lista histórica. O nível ilimitado de desfazer e refazer operações é obtido percorrendo esta lista para trás e para frente, chamando operações Unexecute e Execute, respectivamente.


A chave deste padrão è uma classe abstrata Command, a qual declara uma interface para execução de operações. Na sua forma mais simples, esta interface inclui uma operação abstrata Execute. As subclasses concretas de Command especificam um par receptoração através do armazenamento do receptor como uma variável de instância e pela implementação de Execute para invocar a solicitação. O receptor tem o conhecimento necessário para poder executar a solicitação.


Também conhecido como Action, Transaction (Ação, Transação, respectivamente).
Obtido em http://pt.wikipedia.org/wiki/Command


EXEMPLO:


public class DvdName {


private String titleName;


public DvdName(String titleName) {


this.setTitleName(titleName);


}


public final void setTitleName(String titleNameIn) {


this.titleName = titleNameIn;


}


public final String getTitleName() {


return this.titleName;


}


public void setNameStarsOn() {


this.setTitleName(this.getTitleName().replace(' ','*'));


}


public void setNameStarsOff() {


this.setTitleName(this.getTitleName().replace('*',' '));


}


public String toString() {


return ("DVD: " + this.getTitleName());


}


}


public abstract class CommandAbstract {


public abstract void execute();


}


public class DvdCommandNameStarsOn extends CommandAbstract {


private DvdName dvdName;


public DvdCommandNameStarsOn(DvdName dvdNameIn) {


this.dvdName = dvdNameIn;


}


public void execute() {this.dvdName.setNameStarsOn();


}


}


public class DvdCommandNameStarsOff extends CommandAbstract {


private DvdName dvdName;


public DvdCommandNameStarsOff(DvdName dvdNameIn) {


this.dvdName = dvdNameIn;


}


public void execute() {


this.dvdName.setNameStarsOff();


}


}


class TestCommand {


public static void main(String[] args) {DvdName jayAndBob = new DvdName("Jay and Silent Bob Strike Back");


DvdName spongeBob = new DvdName("Sponge Bob Squarepants - " +"Nautical Nonsense and Sponge Buddies");


System.out.println("as first instantiated");


System.out.println(jayAndBob.toString());


System.out.println(spongeBob.toString());


CommandAbstract bobStarsOn = new DvdCommandNameStarsOn(jayAndBob);


CommandAbstract bobStarsOff = new DvdCommandNameStarsOff(jayAndBob);


CommandAbstract spongeStarsOn = new DvdCommandNameStarsOn(spongeBob);


CommandAbstract spongeStarsOff = new DvdCommandNameStarsOff(spongeBob);


bobStarsOn.execute();spongeStarsOn.execute();


System.out.println(" ");System.out.println("stars on");


System.out.println(jayAndBob.toString());


System.out.println(spongeBob.toString());


spongeStarsOff.execute();System.out.println(" ");


System.out.println("sponge stars off");


System.out.println(jayAndBob.toString());


System.out.println(spongeBob.toString());


}}


UML do Exempo:


AULA 21 e 22 - PADRÃO OBSERVER

O padrão Observer define uma relação de dependência "um-para-muitos" entre objetos, tal que quando há mudança no estado de um objeto, todos os seus dependentes são notificados e atualizados automaticamente. Esse padrão tem como elementos participantes o Subject, que define uma interface para adicionar/remover dependentes e notificar os dependentes; o ConcreteSubject, que retém o estado de interesse dos objetos ConcreteObserver e notifica esses objetos de sua mudança de estado; o Observer que define uma interface para atualizar os objetos que precisam ser notificados das mudanças no Subject e o ConcreteObserver, que implementa a interface de Observer e precisa atualizar o seu estado conforme o estado do Subject ao qual está associado.
No sistema proposto, o padrão Observer é aplicado em: • ControladorDeJogo - É responsabilidade de cada Controlador de Jogo apresentar graficamente o estado atual do jogo. Para isso, o ControladorDeJogo atua como observador (ConcreteObserver) sobre a Sessão, sendo notificado de cada modificação no Estado. • Sessao - A Sessao por sua vez, atua como o objeto observado (ConcreteSubject) notificando os objetos dependentes das mudanças no Estado. • ControladorDeSessoes - O ControladorDeSessoes apresenta ao usuário todas as sessões disponíveis, para que o Controlador possa apresentar toda Sessao recentemente criada e deixe de apresentar aquelas que já terminaram, o controlador atua como observador sobre o ServidorDePartidas, sendo notificado de toda Sessao que é criada ou terminada. • ServidorDePartidas - O ServidorDePartidas, assim como a Sessao, atua como objeto observado tendo como responsabilidade notificar cada ControladorDeSessoes quando uma sessao e criada ou terminada.
Observação: Tendo em vista as constantes alterações no Estado devido a dinâmica do jogo, é interessante que cada ControladorDeJogo seja notificado uma única vez por ciclo, ou seja, permitir que a LogicaDoJogo atualize cada elemento para então notificar os Controladores.

AULA 19 e 20 - PADRÃO SINGLENTON

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.
Nota linguística: O termo vem do significado em inglês quando se resta apenas uma carta nas mãos, num jogo de baralho.
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.
Exemplos

Em Java
Segue um exemplo em Java de classe Singleton usada em log de dados. Esta classe suporta inicialização sob demanda e ambientes multi-thread.public class SingletonLog {
// Construtor privado. Suprime o construtor publico padrao.
private SingletonLog() {
// Leitura da configuração de log. Normalmente descrita em um arquivo.
}
// Faz o log de eventos da aplicacao
public void doLog(String eventDescription) {

}
//Retorna a instancia unica da classe SingletonLog
public static SingletonLog getInstance() {
return SingletonLogHolder.instance;
}
//Classe auxiliar para criacao da instancia. Evita problemas de sincronizacao de threads.
private static class SingletonLogHolder {
private static SingletonLog instance = new SingletonLog();
}
}

AULA 17 e 18 - PADRÕES GOF

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.

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.

Formas de classificação

- Classificação GOF

  • Criação
  • Estrutura
  • Comportamento

- Classificação de hetsker

  • Interface
  • Responsabilidade
  • Construção
  • Operação
  • Extensão

AULA 15 e 16 - COESÃO

Alta coesão é um princípio de ouro que deve ser sempre mantido em mente durante o projeto
Tipos de coesão entre módulos
· Coincidental (pior)
· Lógico
· Temporal
· Procedural
· De comunicação
· Sequencial
· Funcional (melhor)
Coesão coincidental
· Há nenhuma (ou pouca) relação construtiva entre os elementos de um módulo
· No linguajar OO:
· Um objeto não representa nenhum conceito OO
· Uma coleção de código comumente usado e herdado através de herança (provavelmente múltipla)
class Angu {
public static int
acharPadrão(String texto, String padrão) {
// ...
}
public static int média(Vector números) {
// ...
}
public static outputStream abreArquivo(string nomeArquivo) {
// ...
}
}
class Xpto extends Angu { // quer aproveitar código de Angu
...
}
Coesão lógica
· Módulo faz um conjunto de funções relacionadas, uma das quais é escolhida através de um parâmetro ao chamar o módulo
· Semelhante a acoplamento de controle
· Cura: quebrar em métodos diferentes
public void faça(int flag) {
switch(flag) {
case ON:
// coisas para tratar de
ON
break;
case OFF: // coisas para tratar de OFF
break;
case FECHAR:
// coisas para tratar de FECHAR
break;
case COR: // coisas para tratar de COR
break;
}
}

AULA 14 - PADRÃO CONTROLLER

Controller
Problema
Quem deveria receber a responsabilidade de tratar eventos do sistema?
Um evento do sistema é um evento de alto nível gerado por um ator externo
Estão associados a operações do sistema que já vimos nos Diagramas de Sequência do Sistema
Exemplo do estudo de caso: Caixa pressiona "Fim de venda"
Solução
Use um controlador
Um controlador é um objeto que não é de interface GUI responsável pelo tratamento de eventos do sistema
Um controlador define métodos para as operações do sistema
Atribuir a responsabilidade pelo tratamento de eventos do sistema a uma classe de acordo com uma das alternativas abaixo:
Representa o "sistema" como um todo (facade controller)
Representa o negócio ou organização como um todo (facade controller)
Representa algo no mundo real que é ativo (por exemplo, o papel de uma pessoa) que poderia estar envolvido na tarefa (role controller)
Representa um handler artificial de todos os eventos do sistema para um Use Case particular, normalmente chamado "Handler" (use case controller)
Exemplo
No estudo de caso, há várias operações de sistema:
Quem deveria ser o controlador para os eventos do sistema?
Pelo padrão Controller, temos as seguintes alternativas:
Representa o "sistema": TPDV
Representa o negócio ou organização: Loja
Representa algo no mundo real ...: Caixa
Representa um handler artificial ...: CompraItemHandler
A escolha particular depende de fatores discutidos na seção Discussão
Por exemplo, se fosse TPDV, teríamos:
Discussão
De forma geral, o mesmo controlador deve ser usado para todas as operações de um mesmo Use Case de forma a manter a informação de estado do Use Case
A informação de estado pode ser útil para detectar sequências erradas de eventos de sistema
Exemplo: façaPagamento() antes de fimDeVenda()
Não coloque toda a inteligência no controlador
Delegue para outros objetos,para manter coesão
Use um Handler artificial quando as outras alternativas exibem acoplamento alto ou coesão baixa
Quando está surgindo um "God class"
Usado em sistemas mais complexos
Observe que classes "Window", "Applet", "Application", "View", "Document" não devem ser controladores
Tais classes podem receber o evento e delegá-lo ao controlador
Não se deve colocar business logic num objeto de interface com o usuário
Um design correto seria:
Um design incorreto seria:
O Role Controller pode levar a um mau projeto
O fato de algo ser feito por uma pessoa no mundo real não necessariamente significa que isso é uma boa alternativa em software
É mais comum "dar vida aos objetos" (não animados)
Consequências
Maior possibilidade de reuso, já que o business logic não está nos objetos de interface
Exemplo: embutir o business logic num objeto de interface não permitiria fazer EAI (Enterprise Application Integration)
Ajuda a verificar o sequenciamento das operações do sistema, através do estado do controlador
Responsabilidades, Role Playing e Cartões CRC
Embora não faça parte de UML, uma técnica chamada Cartões CRC é muito usada para atribuir responsabilidades durante o projeto
CRC = Class-Responsibility-Collaborations
CRC cards inventadas por Ward Cunningham e Kent Beck (Tektronix)Cartão CRC é um cartão pequeno (para só escrever o essencial) para cada classe
Escreve-se o nome da classe, suas responsabilidades e colaborações
Só pense nas responsabilidades de alto nível
São desenvolvidos em pequenos grupos em que cada pessoa assume o papel (Role) de uma ou mais classes
Mais detalhes aqui:
Designing Object-Oriented Software, Wirfs-Brock, Wilkerson e Wiener; Prentice Hall, 1990.
Algumas pessoas acham que é melhor usar ferramentas gráficas em vez de CRC Controller
Problema
Quem deveria receber a responsabilidade de tratar eventos do sistema?
Um evento do sistema é um evento de alto nível gerado por um ator externo
Estão associados a operações do sistema que já vimos nos Diagramas de Sequência do Sistema
Exemplo do estudo de caso: Caixa pressiona "Fim de venda"
Solução
Use um controlador
Um controlador é um objeto que não é de interface GUI responsável pelo tratamento de eventos do sistema
Um controlador define métodos para as operações do sistema
Atribuir a responsabilidade pelo tratamento de eventos do sistema a uma classe de acordo com uma das alternativas abaixo:
Representa o "sistema" como um todo (facade controller)
Representa o negócio ou organização como um todo (facade controller)
Representa algo no mundo real que é ativo (por exemplo, o papel de uma pessoa) que poderia estar envolvido na tarefa (role controller)
Representa um handler artificial de todos os eventos do sistema para um Use Case particular, normalmente chamado "Handler" (use case controller)
Exemplo
No estudo de caso, há várias operações de sistema:
Quem deveria ser o controlador para os eventos do sistema?
Pelo padrão Controller, temos as seguintes alternativas:
Representa o "sistema": TPDV
Representa o negócio ou organização: Loja
Representa algo no mundo real ...: Caixa
Representa um handler artificial ...: CompraItemHandler
A escolha particular depende de fatores discutidos na seção Discussão
Por exemplo, se fosse TPDV, teríamos:
Discussão
De forma geral, o mesmo controlador deve ser usado para todas as operações de um mesmo Use Case de forma a manter a informação de estado do Use Case
A informação de estado pode ser útil para detectar sequências erradas de eventos de sistema
Exemplo: façaPagamento() antes de fimDeVenda()
Não coloque toda a inteligência no controlador
Delegue para outros objetos,para manter coesão
Use um Handler artificial quando as outras alternativas exibem acoplamento alto ou coesão baixa
Quando está surgindo um "God class"
Usado em sistemas mais complexos
Observe que classes "Window", "Applet", "Application", "View", "Document" não devem ser controladores
Tais classes podem receber o evento e delegá-lo ao controlador
Não se deve colocar business logic num objeto de interface com o usuário
Um design correto seria:
Um design incorreto seria:
O Role Controller pode levar a um mau projeto
O fato de algo ser feito por uma pessoa no mundo real não necessariamente significa que isso é uma boa alternativa em software
É mais comum "dar vida aos objetos" (não animados)
Consequências
Maior possibilidade de reuso, já que o business logic não está nos objetos de interface
Exemplo: embutir o business logic num objeto de interface não permitiria fazer EAI (Enterprise Application Integration)
Ajuda a verificar o sequenciamento das operações do sistema, através do estado do controlador
Responsabilidades, Role Playing e Cartões CRC
Embora não faça parte de UML, uma técnica chamada Cartões CRC é muito usada para atribuir responsabilidades durante o projeto
CRC = Class-Responsibility-Collaborations
CRC cards inventadas por Ward Cunningham e Kent Beck (Tektronix)Cartão CRC é um cartão pequeno (para só escrever o essencial) para cada classe
Escreve-se o nome da classe, suas responsabilidades e colaborações
Só pense nas responsabilidades de alto nível
São desenvolvidos em pequenos grupos em que cada pessoa assume o papel (Role) de uma ou mais classes
Mais detalhes aqui:
Designing Object-Oriented Software, Wirfs-Brock, Wilkerson e Wiener; Prentice Hall, 1990.
Algumas pessoas acham que é melhor usar ferramentas gráficas em vez de CRC