[Observer] Due classi completamente indipendenti

di il
11 risposte

[Observer] Due classi completamente indipendenti

Buongiorno ,

Sono alle prese con due classi che appartengono rispettivamente a due librerie differenti .
Nel main vengono solamente istanziate e lavorano in modo indipendente su eventi, ovvero ogni loro metodo viene eseguito s'è basato sulla
generazione di uno o più eventi . L'evento di una classe non ha niente a che fare con l'evento dell' altra classe.
Nel main o in una terza classe dovrei fare anche da "ponte", ovvero dovrei informare entrambe le classi se è stato generato un evento che sia di una o dell'altra classe.

esempio :

Classe A - Evento generato ? Se sì informa Classe B, altrimenti non fare nulla
Classe B - Evento generato ? Se sì informa Classe A, altrimenti non fare nulla
Per fare questo ho letto su internet che è consigliabile usare Observer, ma prima di andare a fare cose troppo complicate per me , vorrei chiedere
un parere

Grazie

11 Risposte

  • Re: [Observer] Due classi completamente indipendenti

    Cyrano ha scritto:


    Per fare questo ho letto su internet che è consigliabile usare Observer, ma prima di andare a fare cose troppo complicate per me , vorrei chiedere un parere
    Il Pattern Observer permette ad un oggetto subject, il "soggetto" (o observable) di notificare N altri oggetti detti observer quando c'è un cambiamento del suo stato interno ma attenzione, notificando attraverso una astrazione, in modo che l'observable non debba "sapere" nulla di specifico di dove/quali sono le classi degli observer. Infatti tipicamente Observer è una interfaccia.

    Non necessariamente devi implementarlo da zero. Nel framework standard, package java.util, c'è già una implementazione del pattern. Solo con una limitazione/variante legata al fatto che Observable è una classe e non invece una interfaccia come in teoria dovrebbe essere.
  • Re: [Observer] Due classi completamente indipendenti

    Per fare un esempio pratico ho recuperato questo codice dal web. Qui però abbiamo solo una classe osservabile per rendere le cose più semplici.
    
    import java.util.Observable;
    import java.util.Observer;
    
    class MessageBoard extends Observable {
      private String message;
    
      public String getMessage() {
        return message;
      }
    
      public void changeMessage(String message) {
        this.message = message;
        setChanged();
        notifyObservers(message);
      }
    
      public static void main(String[] args) {
        MessageBoard board = new MessageBoard();
        Student bob = new Student();
        Student joe = new Student();
        board.addObserver(bob);
        board.addObserver(joe);
        board.changeMessage("More Homework!");
      }
    }
    
    class Student implements Observer {
      public void update(Observable o, Object arg) {
        System.out.println("Message board changed: " + arg);
      }
    }
    
    Cosa fa questo codice?Questo è quello che ho capito (scusate il neretto).

    Voglio monitorare la mia classe MessageBoard quindi eredito da Observable.
    MessageBoard è quindi la classe che vogliamo monitorare.
    La classe Student è la classe che informiamo ogni volta che avviene un cambiamento in MessageBoard

    Nel main , aggiungo due Observer di nome Bob e Joe che verranno informati ad ogni cambiamento in MessageBoard.

    Genero un cambiamento in MessageBoard :
    board.changeMessage("More Homework!");
    MessageBoard ereditando da Observable chiama il metoto
    notifyObservers(message);
    il quale informa gli Observer
    chiamando
    update(Observable o, Object arg)
    contenuto sempre dentro ogni Observer

    Secondo te ho capito bene ?
  • Re: [Observer] Due classi completamente indipendenti

    Cyrano ha scritto:


    Voglio monitorare la mia classe MessageBoard quindi eredito da Observable.
    MessageBoard è quindi la classe che vogliamo monitorare.
    La classe Student è la classe che informiamo ogni volta che avviene un cambiamento in MessageBoard

    Nel main , aggiungo due Observer di nome Bob e Joe che verranno informati ad ogni cambiamento in MessageBoard.

    Genero un cambiamento in MessageBoard :
    board.changeMessage("More Homework!");
    MessageBoard ereditando da Observable chiama il metoto
    notifyObservers(message);
    il quale informa gli Observer
    chiamando
    update(Observable o, Object arg)
    contenuto sempre dentro ogni Observer

    Secondo te ho capito bene ?
    Sì, tutto corretto.

    (i nomi bob e joe sono solo variabili locali nel main ... l'Observable non ne "sa" nulla di questi nomi; giusto solo per precisare)
  • Re: [Observer] Due classi completamente indipendenti

    Grazie come sempre
  • Re: [Observer] Due classi completamente indipendenti

    Edit:
    Domanda mal posta
  • Re: [Observer] Due classi completamente indipendenti

    Buongiorno ,

    Nella classe che implementa Observer , all'interno del metodo
    public void update(Observable o, Object arg)
    è possibile
    ottenere l'istanza della classe che ha generato l'evento o almeno identificare il sender ?
    Diversamente potrei inserirlo nel messaggio dell'evento e quindi ottenerlo da
    Object arg
    ma ho sempre il dubbio fi fare le cose nel modo più complicato..
  • Re: [Observer] Due classi completamente indipendenti

    Cyrano ha scritto:


    Nella classe che implementa Observer , all'interno del metodo
    public void update(Observable o, Object arg)
    è possibile
    ottenere l'istanza della classe che ha generato l'evento o almeno identificare il sender ?
    Nel update() il "sender" è quel primo parametro, il Observable. Se hai fatto una classe X extends Observable, allora quando X notifica gli observer, quel primo argomento è il riferimento proprio alla istanza di X, ovviamente "vista" come Observable. Se nel update sei certo (ma puoi testarlo) che il tipo è X, puoi anche fare un cast a X se hai bisogno di fare operazioni specifiche di X.

    Cyrano ha scritto:


    Diversamente potrei inserirlo nel messaggio dell'evento e quindi ottenerlo da
    Object arg
    Il Object arg lo può specificare l'observable quando notifica gli observer con notifyObservers(Object arg)

    L'oggetto può essere quello che ti pare: una stringa che fa da "tag" per indicare cosa è cambiato; un messaggio testuale informativo; un oggetto più complesso che descrive le modifiche. DIPENDE da come/dove lo si vuole usare.


    P.S. Come detto prima, la implementazione del pattern Observer nel framework è solo UNA delle possibili implementazioni. Oltretutto nemmeno "perfetta" (Observable è una classe, questo limita abbastanza l'applicabilità).

    Nessuno ti vieta di implementare l'Observer per conto tuo, che ti assicuro non è nulla di ché ...
    (dai una sbirciatina al sorgente di Observable fornito da Oracle)
  • Re: [Observer] Due classi completamente indipendenti

    Per l'argomento arg avrei creato prima questa classe:
    
    public class Message {
        public String client;
        public String author;
        public String msg;
        public String channel;
        
        void build( String client, String author, String msg, String channel ){
        
            this.client  = client;
            this.author  = author;
            this.msg     = msg;
            this.channel = channel;
        }
    }
    
    Quindi all'interno di un metodo di una classe che gestisce determinati eventi ho scritto:
    
    public void onMessageReceived(MessageReceivedEvent event){
                //.......// 
     msgObj.build("Client", author, msg, channel);
     dEvent.changeMessage(msgObj);  // -> Genero l'evento
    }
    

    dove
    
     public void changeMessage(Message msg) {
                this.message = msg;
                setChanged();
                notifyObservers(msg);
            }
    
    e quindi in Observer :
    
    static class Event implements Observer {
        
        @Override
        public void update(Observable o, Object arg) {
            
            Message msgObj;
            msgObj = (Message) arg;
    }
    
    Posso fare anche il casting di arg ?(non di Observable)
    Chiedo perchè mi da errore
    
    java.lang.ClassCastException: java.lang.String cannot be cast to messages.Message
    at messages.Main$Event.update(Main.java:57)
    at java.util.Observable.notifyObservers(Observable.java:159)
    
    Cosa c'entra java.lang.String ?

    Edit:
    vado a vedere il codice di Observable:159
  • Re: [Observer] Due classi completamente indipendenti

    Cyrano ha scritto:


    
    public class Message {
        public String client;
        public String author;
        public String msg;
        public String channel;
        
        void build( String client, String author, String msg, String channel ){
        
            this.client  = client;
            this.author  = author;
            this.msg     = msg;
            this.channel = channel;
        }
    }
    
    Alt! Buona programmazione OOP:
    - campi private
    - setter e/o getter public
    - costruttore public (non quel build)

    C'è però una considerazione generale. L'oggetto di "argomento" viene passato a tutti gli observer registrati. Se l'oggetto fosse "mutabile" (con i setter), che succederebbe se un observer ne cambia lo stato e poi l'oggetto passa ad un altro observer? Si vuole proprio così? Dipende ...

    In questi casi sarebbe meglio stare sulla difensiva: oggetti immutabili, quindi campi private final, solo i getter e chiaramente un costruttore appropriato.

    Cyrano ha scritto:


    Posso fare anche il casting di arg ?
    Certo ... è quello che hai appena fatto.

    Cyrano ha scritto:


    Chiedo perchè mi da errore
    
    java.lang.ClassCastException: java.lang.String cannot be cast to messages.Message
    
    Sto ancora cercando questa "String"
    Da qualche parte stai facendo un notifyObservers con un String .... non c'è molto altro da pensare.
  • Re: [Observer] Due classi completamente indipendenti

    Scusami...Si stavo passando una stringa................

    ah è vero! Final permette definire i field solo una volta e con il costruttore
    Raccolgo tutte le osservazioni che mi hai fatto e correggo !Grazie
  • Re: [Observer] Due classi completamente indipendenti

    Cyrano ha scritto:


    Final permette definire i field solo una volta
    un field a cui si può assegnare un valore una sola volta.
Devi accedere o registrarti per scrivere nel forum
11 risposte