PDA

View Full Version : [Java] Realizzare il pattern Observer


e-commerce84
19-05-2010, 11:56
Ciao,
stò studiando i pattern applicati a Java.
Attualmente mi stò vedendo il pattern Observer che viene usato praticamente in tutte le GUI.

Mi dite se ho capito bene?

Allora io ho sostanzialmente ho due tipi di oggetti:
1) Un SOGGETTO (o publisher) che di fatto rappresenta i miei dati.
2) Vari OBSERVER (o listener) che di fatto rappresentano una specifica vista dei mie dati (mantenendosi sincronicatti con il soggetto)

La logica che ci stà dietro è la seguente: Il soggetto rappresenta i miei dati e si manterrà una lista di tutti gli osservatori che lo stanno osservando (che vogliono quindi rappresentare i dati e le loro modifiche quando esse avvengono).
Quando i dati subiscono una modifica il soggetto invia una notifica a tutti i suoi osservatori che si auto aggiorneranno e forniranno una nuova vista dei dati.

(Es: ho un foglio di excell. I dati nel sistema sono il soggetto. La rappresentazione è l'osservatore. Tramite l'osservatore modifico il valore di una cella. Il soggetto ricalcola con una formula i valori di tutte le altre celle del foglio di calcolo che vengono così modificate, così avverte l'osservatore della modifica, esso si aggiorna e visualizza i nuovi valori di tutte le celle)

Esempio in codice:

Observer la dichiaro come un'interfaccia, poi ovviamente devo implementarla ed in base al tipo concreto dell'Observer il metodo update aggiornerà la vista o farà qualcosa in uno specifico modo:


/* Interfaccia che rappresenta i vari oggetti osservatori che a loro volta
* rappresentano una specifica rappresentazione dei dati
*/

public interface Observer {
public void update(Subject subject) ; // Metodo astratto che modifica i dati
}


Subject:


import java.util.Vector;

/* Classe che rappresenta i dati su cui si basano le viste */

public class Subject{

/* Crea un vettore che conterrà la lista di tutti gli osservatori che lo
* osservano */
protected Vector observers = new Vector();

public void addObserver(Observer o){ // Aggiunge un oggetto Observer al vettore
observers.addElement(o);
}

public void removeObserver(Observer o){ // Rimuove un osservatore dal vettore
observers.removeElement(o);
}

/* Notifica agli oggetti osservatori che c'è stata una modifica dei dati
* rappresentati da Subject */
public void notify(){
Enumeration e = observers.getElements();

while (e.hasMoreElements()) {
/* Invoca il metodo update su tutti gli osservatori per modificare le viste */
((Observer)e.nextElement()).update(this);
}
}
}


mmm...il mio ragionamento è corretto?

Grazie

nuovoUtente86
19-05-2010, 12:42
Il pattern observer, realizza il relazionamento 1-molti tra il subject ed n ascoltatori, in modo che ogni variazione di stato dell' observable sia ascoltata in broadcast dagli observer. Ovviamente tale logica trova un' applicazione nello slegare i dati applicativi dalla loro rappresentazione. Ad esempio 2 observer potrebbero consumare i dati: uno per mostrarli a video e l' altro per loggarli su file o mandarli in rete.

e-commerce84
19-05-2010, 17:03
Ti ringrazio,
mmm...ora però ho un altro problemino con un altro esempio più concreto che non mi gira (purtroppo sono tremendamente arrugginito con Java e diciamo che non ci ho mai fatto nulla di che)

L'esempio è questo:

INTERFRACCIA Observer:

/* Rappresenta un generico oggetto osservatore */

public interface Observer {
void update();
}


CLASSE ConcreteObserver:

/* Implementa l'interfaccia Observer e rappresenta uno specifico tipo di oggetto
* osservatore */

public class ConcreteObserver implements Observer{

// Specifica quale suggetto stà osservando l'oggetto osservatore
private ConcreteSubject subject;

/* COSTRUTTORE: crea uno specifico osservatore e gli passa il riferimento
* all'oggetto soggetto che si intende osservare */
public ConcreteObserver(ConcreteSubject aSubject){
subject = aSubject;
subject.add(this);
}

/* Metodo pubblico che viene invocato dal soggetto per modificare lo stato
* dell'osservatore quando nel soggetto avviene una modifica */
public void update(){
System.out.println("Io sono l'observer " + this +
" ed il nuovo stato del mio subject e' " + subject.getState());
}

}


INTERFACCIA Subject:

/* Interfaccia che rappresenta un generico soggetto che rappresenta i dati */

public interface Subject {
void add(Observer anObserver); // Aggiunge un elemento lista degli osservatori
void remove(Observer anObserver); // Rimuove un elemento dalla lista degli osservatori
void notify(); // Notifica a tutti gli oggetti osservatori una modifica sui dati
}


CLASSE ConcreteSubject (che contiene anche il metodo main() ):

import java.util.LinkedList;

/* Rappresenta un tipo concreto di Subject ed implementa l'interfaccia Subject */

public class ConcreteSubject implements Subject {

private int state; // Rappresenta lo stato del soggetto (il dato rappresentato)


private LinkedList observers; // Rappresenta la lista degli osservatori

/* Creatore: Crea un oggetto di tipo ConcreteSubject e riceve come input il
* dato che si intende rappresentare (lo stato iniziale del soggetto) */
public ConcreteSubject(int initialState){
state = initialState; // Setta lo stato
}

/* Metodo pubblico che restituisce al chiamante il valore dello stato del
* soggetto */
public int getState(){
return state;
}

/* Metodo pubblico che permette la modifica dello stato del soggetto */
public void setState(int aState) {
state = aState;
}

/* Metodo pubblico che permette di inserire un oggetto osservatore nella lista
* di ogetti che osservano il soggetto */
public void add(Observer anObserver) {
observers.add(anObserver);
}

/* Metodo pubblico che permette di rimuovede un oggetto osservatore dalla lista
* di ogetti che osservano il soggetto */
public void remove(Observer anObserver) {
observers.remove(anObserver);
}

/* Metodo pubblico che notifica agli oggetti osservatori eventuali modifiche
* dei dati nel soggetto */
public void notify(){
Iterator iter=observers.iterator(); // Crea un iteratore su observer
Observer obs; // Contiene il riferimento ad un generico Observer
while(iter.hasNext()){ // Aggiorna tutti gli observer
obs=(Observer)iter.next();
obs.update();
}

/* Metodo main() che avvia l'applicazione: prende in input un array di
* argomenti */
public static void main(String[] args){

// Crea un array di osservatori di 3 locazioni
int concreteObservers[3];
int initialState = 10; // Setta a 10 la variabile initialState

// Crea un nuovo soggetto concreto passandogli uno stato iniziale
ConcreteSubject mySubject = new ConcreteSubject(initialState);
// Stampa lo stato del soggetto appena creato
System.out.println("E' stato creato un subject con stato " +
mySubject.getState());

/* Crea tre oggetti osservatori e mette il loro riferimento nell'array
* concreteObservers */
for (int i = 0; i < 3; i++){
concreteObservers[i] = new ConcreteObserver(mySubject);
}

System.out.println("...");
mySubject.setState(17); // Cambia il valore dello stato del soggetto
mySubject.notify(); // Notifica il cambiamento di stato agli oggetti osservatori
System.out.println("...");
mySubject.setState(06); // Cambia il valore dello stato del soggetto
mySubject.notify(); // Notifica il cambiamento di stato agli oggetti osservatori
}

}


Praticamente eclipse mi segnala una sorta di warning: "Cannot override the final method from Object" alla linea:
void notify(); di Subject (forse c'entra con quella cosa che mi dicevi prima?)

E poi mi dà una serie di errori dentro la classe ConcreteSubject.

Gli errori che mi dà sono:


Cannot override the final method from Object ConcreteSubject.java /Observer3/src line 43 Java Problem
Iterator cannot be resolved to a type ConcreteSubject.java /Observer3/src line 44 Java Problem
Syntax error on token "3", delete this token ConcreteSubject.java /Observer3/src line 56 Java Problem
Syntax error, insert "}" to complete Block ConcreteSubject.java /Observer3/src line 48 Java Problem
Type mismatch: cannot convert from ConcreteObserver to int ConcreteSubject.java /Observer3/src line 68 Java Problem
LinkedList is a raw type. References to generic type LinkedList<E> should be parameterized ConcreteSubject.java /Observer3/src line 10 Java Problem
Type safety: The method add(Object) belongs to the raw type LinkedList. References to generic type LinkedList<E> should be parameterized ConcreteSubject.java /Observer3/src line 32 Java Problem

Non capisco...l'esempio è prefetto...preso dal sito di un corso universitario...booo

Darecon
19-05-2010, 17:35
Chiamalo notifica, notify e' un metodo di object che viene ereditato, e tu cosi' tenti di sovrascriverlo.. ;)

e-commerce84
19-05-2010, 19:36
Chiamalo notifica, notify e' un metodo di object che viene ereditato, e tu cosi' tenti di sovrascriverlo.. ;)

Vero :-)