Observer: diferenças entre revisões

Conteúdo apagado Conteúdo adicionado
Revertendo para a revisão 27670701 de 2011-11-18 01:51:38 por Luís Felipe Braga usando popups
Linha 1:
{{sem-fontes|data=Fevereiro de 2008}}
O padrão '''Observer''' (também conhecido como Dependents, Publish-Subscribe) é um [[Padrões de projeto de software|padrão de projeto de software]] (do [[língua inglesa|inglês]] ''design pattern''), considerado um padrão comportamental, define um dependência '''um-para-muitos''', onde permite que a modificação do estado de um [[Orientação a objetos|objeto]], notifique seus dependentes, sendo atualizados automaticamente.<ref>FREEMAN, Eric; FREEMAN Elisabeth. Use a Cabeça (head first) Padrões de Projeto. – Rio de Janeiro : Alta Books, 2007.</ref>
{{Reciclagem|data=Fevereiro de 2008}}
==Aplicação==
Pode ser utilizado quando existe uma [[Abstração#Computa.C3.A7.C3.A3o|abstração]] de dois aspectos, sendo um dependente do outro, ou também quando um objeto sofre uma mudança obriga mudança em outros objetos, sem saber quantos objetos precisam mudar, ou quando pode ser capaz de notificar outros objetos, sem que os objetos sejam fortemente acoplados.
<p>O padrão '''Observer''' é tão útil que [[Java (linguagem de programação)|Java]] contém uma imprementação dele em seus pacotes. A classe Observable e a interface Observer formam o padrão.<ref>http://www.i2p.com.br/ricardo/observer.pdf</ref></p>
 
O '''Observer''' é um [[padrão de projeto de software]] que define uma dependência ''um-para-muitos'' entre objetos de modo que quando um [[objeto]] muda o estado, todos seus dependentes sejam notificados e atualizados automaticamente. Permite que objetos interessados sejam avisados da mudança de estado ou outros eventos ocorrendo num outro objeto.
==Estrutura==
 
O padrão Observer é também chamado de ''Publisher-Subscriber'', ''Event Generator'' e ''Dependents''.
[[imagem:Observer-structure.png |estilo|alinhamento|dimensão|Estrutura básica do padrão Observer]]
 
==Motivação==
<ref>GAMMA, Erich et al. Padrões de Projeto: soluções reutilizáveis de software orientado a objetos. – Porto Alegre: Bookman, 2000.</ref>
 
Um objeto que possua agregações deve permitir que seus elementos sejam acessados sem que a sua estrutura interna seja exposta. De uma maneira geral pode-se desejar que estes elementos sejam percorridos em várias ordens.
== Participantes ==
=== Subject (Sujeito) ===
*fornece uma interface para acrescentar e remover objetos.
=== Observer (Observador) ===
*fornece uma interface com um metodo chamado update() que permite a atualização de todos os objetos dependentes, quando existe mudança no estado de Subject.
=== ConcreteSubject (Sujeito concreto) ===
*implementa os métodos da interface Subject, e ainda o um outro método notifyObservers(), utilizado para a atualização dos observadores sempre que o estado for alterado. Alem de poder possuir métodos que permitam definir seu estado.
=== ConcreteObserver (Observador concreto) ===
* armazena estados que devem permanecer consistentes com os do Subject, podendo ser qualquer classe que implemente a interface Observer, para manter seu estado consistente com o do subject.
== Interação ==
O ConcreteSubject notifica seus observadores sempre que ocorrer uma mudança, permitindo assim ter uma consistencia dos estados entre ele e seus observadores.
Posteriormente ao ser informado, um objeto ConcreteObserver poderá consultar as informações do subject, conciliando suas informações.
Pode haver inumeras interfaces do usuário para os mesmos dados, onde o padrão observer permite estabelecer tais relacionamentos.
Um subject pode ter diversos observadores dependentes, onde todos são notificados quando o subject sofre uma mudança de estado, sendo apenas o publicador de notificações, enviando essas notificações sem precisar saber quem são os observadores.
== Consequências ==
O padrão Observer permite sujeitos e observadores de foma independente.
=== Vantagens e Desvantagens ===
* Assim Tanto observadores quando sujeitos observados podem ser reutilizados e ter sua interface e implementação alteradas sem afetar o sistema;
* Acoplamento forte reduzido com o uso de interfaces e classes abstratas;
* Permite tembem acrescentar observadores sem modificar o sujeito ou outros observadores;
* Acoplamento abstrato entre Subject e Observer - O sujeito não conhece a classe concreta de nenhum observador, permitindo que o acoplamento entre o sujeito e os observadores é abstrato e mínimo;
* Suporte para comunicações do tipo broadcast - a notificação é transmitida automaticamente para todos os objetos interessados, sendo que o sujeito não se preocupa com quantos objetos interessados existem;
* Atualizações inesperadas - Critérios de depêndencia que não estão bem-definidos ou mantidos normalmente conduzem a atualização normais que podem ser difíceis de detectar;
* Não é necessário o acoplamento direto entre os observados e os observadores;
* Um único evento pode ser transmitido para um número qualquer de observadores;
Além das vantagens do acoplamento redizido, da facilidade para efetuar "broadcasting",
e de uma implementação simples da execução da concorrente, em algumas situações em sistema baseado em notificação de eventos é mais eficiente,por exemplo, quando longas cadeias de mensagens podem ser comprimidas em um único nível de indireção.<ref>LARMAN, Craig. Utilizando UML e padrões:uma introdução à análise e ao projeto orientados a objetos e ao desenvolvimento interativo. 3ª. Ed. Porto Alegre:Bookman, 2007.</ref>
 
Como garantir que objetos que dependem de outro objeto percebam as mudanças naquele objeto?
== Implementação ==
A seguir demonstra um código fonte em Java, onde representamos uma sala de aula, que possui como sujeito concreto a classe Sinal e Professora, que implementa a inteface Sujeito, e seus observadores temos a classe Aluno e Estagiaria, que implementa a inteface Observer.
=== Aspectos da implemetação === <ref>http://www.deinf.ufma.br/~vidal/Topicos/observer.pdf</ref>
Antes da implementação deve-se verificar:
* mapeamento entre subjects e observers;
* observando mais de um Subject;
* quem inicia a atualização ?;
* quem dispara a atualização ?;
* referências pendentes;
* estado autoconsistente do Subject;
* protocolos de atualização;
* modificações explícitas de interesse;
* encapsulando semântica de atualizações complexas;
=== Subject ===
==== Classe Sujeito ====
Especifica todos as ações comuns aos sujeitos concretos, que podem adicionar os observadores, remove-los e notifica-los.
<source lang="java">
// <<interface>> Subject
 
* Os observadores (observer) devem conhecer o objeto de interesse.
package br.padroesdeprojeto.observer.saladeaula; //pacote onde foi criado
* O objeto de interesse (subject) deve notificar os observadores quando for atualizado.
 
Os objetos devem-se interligar entre si de forma a que não se conheçam em tempo de [[compilação]] de forma a criar o acoplamento e desfazê-lo a qualquer momento em tempo de execução. Solucionar isso fornece uma implementação muito flexível de acoplamento de [[abstração|abstrações]].
// fornece a interface que sera utilizada pelos ConcreteSubject(Professora, Sirene)
public interface Sujeito {
 
==Aplicabilidade==
public void addObservador(Observador o);
public void removeObservador(Observador o);
public void notificaObservadores();
}
</source>
=== Observer ===
==== Classe Observador ====
Especifica todos as ações comuns aos obsevadores concretos, que podem ser atualizados.
<source lang="java">
// <<interface>> Observer
 
O padrão Observer pode ser usado quando uma abstração tem dois aspectos, um dependente do outro. [[Cápsula|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 ou 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.
package br.padroesdeprojeto.observer.saladeaula; //pacote onde foi criado
 
// fornece a interface que será utilizada pelo ConcreteObserver(Aluno, Estagiaria)
public interface Observador {
public void Update(Sujeito s);
}
</source>
=== ConcreteSubject ===
==== Classe Professora ====
Implementa todas as funções do Subject adicionando e removendo observadores, alem de poder possuir métodos que permitam definir seu estado. Assim ele possui dois observadores que é os observadores concretos Aluno e Estagiaria.
<source lang="java">
//ConcreteSubject2
 
package br.padroesdeprojeto.observer.saladeaula; //pacote onde foi criado
 
import java.util.ArrayList;
 
public class Professora implements Sujeito{
 
private ArrayList<Observador> observadores;
private String comando;
public Professora(){
this.observadores = new ArrayList<Observador>();
}
public void addObservador(Observador o) { // adiciona o observador
this.observadores.add(o);
}
 
public void removeObservador(Observador o) { // remove o observador
this.observadores.remove(o);
}
 
public void notificaObservadores() { // notifica os observadores
for(int i = 0; i<this.observadores.size(); i++)
this.observadores.get(i).Update(this);
}
 
public String getComando() {
return comando;
}
 
public void setComando(String comando) {
this.comando = comando;
this.notificaObservadores();
}
}
</source>
==== Classe Sirene ====
Implementa todas as funções do Subject adicionando e removendo observadores, alem de poder possuir métodos que permitam definir seu estado. Assim como o sujeito concreto Professora ele possui dois observadores que é os observadores concretos Aluno e Estagiaria.
<source lang="java">
//ConcreteSubject1
 
package br.padroesdeprojeto.observer.saladeaula; //pacote onde foi criado
 
import java.util.ArrayList;
 
 
public class Sirene implements Sujeito{
private boolean alertaSonoro;
private ArrayList<Observador> observadores;
public Sirene(){
this.observadores = new ArrayList();
}
 
public void addObservador(Observador o) { // adiciona o observador
this.observadores.add(o);
}
 
public void removeObservador(Observador o) { // remove o observador
this.observadores.remove(o);
}
 
 
public boolean isAlertaSonoro() {
return alertaSonoro;
}
 
public void setAlertaSonoro(boolean alertaSonoro) {
this.alertaSonoro = alertaSonoro;
this.notificaObservadores();
}
public void notificaObservadores() { // notifica os observadores
for(int i=0; i<this.observadores.size(); i++)
this.observadores.get(i).Update(this);
}
}
</source>
=== ConcreteObserver ===
==== Classe Aluno ====
Implementa todas as funções do Observador que armazena estados que devem permanecer consistentes com os do sujeito concreto para manter seu estado consistente com o do subject.
<source lang="java">
// ConcreteObserver1
 
package br.padroesdeprojeto.observer.saladeaula; //pacote onde foi criado
 
public class Aluno implements Observador{
 
public Aluno(){} //Construtor padrão
 
public void Update(Sujeito s) {
if(s instanceof Sirene)
System.out.println(" Aluno - Hora de entregar a prova!");
else
if(s instanceof Professora)
System.out.println(" Aluno - A professora disse: " + ((Professora) s).getComando());
}
}
</source>
==== Classe Estagiaria ====
Assim como a classe Aluno, essa classe implementa todas as funções do Observador que armazena estados que devem permanecer consistentes com os do sujeito concreto para manter seu estado consistente com o do subject.
<source lang="java">
//ConcreteObserver2
 
package br.padroesdeprojeto.observer.saladeaula; //pacote onde foi criado
 
 
public class Estagiaria implements Observador {
public Estagiaria(){} // construtor padrão vazio da classe Observador
 
// implementa o método do Observador
public void Update(Sujeito s) {
if(s instanceof Sirene)// se o ConcreteSubject sirene for acionada
System.out.println(" Estagiaria - Tenho que recolher as provas!");
else
if(s instanceof Professora) // se o ConcreteSubject professora for acionada
System.out.println(" Estagiaria - A professora disse: " + ((Professora) s).getComando());
}
}
</source>
=== Classe Main ===
Tem como função de demostrar um exemplo de execução e troca de comportamento de objetos em tempo de execução pelo padrão Observer.
<source lang="java">
// classe principal
 
package br.padroesdeprojeto.observer.saladeaula; //pacote onde foi criado
 
// Classe principal do programa
public class Main {
public static void main(String[] args){
 
// inicializando os sujeito(ConcreteSubject), no caso uma Sirene e uma Professora, mas poderia haver varios sujeitos
Sirene sirene = new Sirene();
Professora professora = new Professora();
// inicialização dos observadores(ConcreteObserver), no caso são quatro observadores, sendo tres alunos e uma estagiaria,
// mas poderia haver varios observadores
Observador aluno1 = new Aluno();
Observador aluno2 = new Aluno();
Observador aluno3 = new Aluno();
Observador estagiaria = new Estagiaria();
 
// adicionando-os como observadores do ConcreteSubject no caso a Sirene
sirene.addObservador(aluno1);
sirene.addObservador(aluno2);
sirene.addObservador(aluno3);
sirene.addObservador(estagiaria);
 
// adicionando-os como observadores do ConcreteSubject no caso a Professora
professora.addObservador(aluno1);
professora.addObservador(aluno2);
professora.addObservador(aluno3);
professora.addObservador(estagiaria);
// aplicando uma ação ao Subject Professora
professora.setComando("Vamos aplicar a prova!");
System.out.println("\n 50 min depois\n IIIINNNFFFOOO");
// aplicando uma ação ao Subject Sirene
sirene.setAlertaSonoro(true);
}
}
</source>
== Estrutura do código fonte ==
Em relação ao código acima apresentado representamos uma sala de aula, onde representamos tres alunos e uma estagiaria como observadores que ficam esperando uma ação dos observados, alem de termos dois observados que são os sujeitos professora e sirene.
<p>No código existe dois sujeitos concretos que implementa os métodos da interface Sujeito, dois observadores concretos que implementam a interface Observador. Os observadores visualizam as atualizações dos dois sujeitos concretos.</p>
 
[[imagem:Observer-structureSourceCode.png |estilo|alinhamento|dimensão|Estrutura do padrão Observer em relação ao código fonte]]
 
Após serem informados das atualizações dos estados do sujeito concreto que está sendo observado, os observadores concretos realizam uma determinada ação. Assim como as classes Aluno e Estagiaria observam os estados das classes Sirene e Professora, eles podem deixarem de ser observador de um ou dos dois, e também ser observador de mais observadores.
 
== Referências ==
<references/>
 
=={{Ligações externas}}==