Pattern di osservatore senza cambio di stato?

1

La mia domanda è se esiste un modello simile a Observer che non implica un cambiamento di stato nell'oggetto osservato. Quello che segue è un esempio concreto:

Ho una classe ConnectionFactory che è responsabile della creazione di connessioni al database JDBC. Ora ho bisogno di fare qualcosa con ogni connessione subito dopo che è stata creata (in particolare, ho bisogno di impostare una variabile definita dall'utente nella sessione MySQL) ma non voglio farlo nella classe ConnectionFactory dal Sento che questo è qualcosa che va oltre le sue responsabilità.

Ho preso in considerazione la possibilità di rendere ConnectionFactory estendere java.util.Observable e di avere una classe Observer che verrà notificata ogni volta che viene creata una connessione. Tuttavia sembra che questo approccio non sia corretto, dal momento che il pattern Observer implica che l'oggetto osservato viene osservato per le modifiche dello stato , ma lo stato di ConnectionFactory non cambia affatto quando viene creata una connessione.

Come puoi vedere, devo aggirare questo problema simulando una modifica di stato prima di chiamare notifyObservers() (altrimenti gli osservatori non saranno avvisati) e sincronizzare queste due affermazioni per assicurarci che lo "stato sia cambiato" il flag impostato nella prima istruzione è ancora attivo quando viene eseguita la seconda istruzione. Questo tipo di soluzione alternativa aumenta il mio sospetto di aver preso l'approccio sbagliato.

public class ConnectionFactory extends java.util.Observable {

    public static final ConnectionFactory INSTANCE = new ConnectionFactory();

    private ConnectionFactory(){};

    public Connection makeConnection(){

        Connection connection = null;

        // ... obtain the connection ...

        synchronized(this) {
            this.setChanged();
            this.notifyObservers(connection);
        }

        return connection;
    }       
}
public class Foo implements java.util.Observer {

    @Override
    public void update(Observable o, Object arg) {

        Connection con = (Connection)arg;

        // ... set MySQL user-defined variables ...

    }
}
// Somewhere in initialization code...
ConnectionFactory.INSTANCE.addObserver(new Foo());

Quindi c'è un oggetto che voglio osservare, c'è una classe che deve fare qualcosa quando l'oggetto osservato attiva certi eventi, ma quegli eventi sono cambiamenti di stato non . Se il pattern Observer non è applicabile, quale sarebbe l'approccio corretto?

    
posta abl 14.03.2015 - 14:24
fonte

2 risposte

7

Puoi:

  1. Utilizza le funzionalità di Observer di cui hai bisogno e ignora le altre funzionalità; o
  2. Utilizza qualche altro modello di software che corrisponda maggiormente a quello che ti serve, o
  3. Non utilizzare affatto un modello e scrivi semplicemente il codice che risolve il problema.

Solo perché l' articolo di Wikipedia dice che il pattern Observer è progettato per notificare all'osservatore cambiamenti di stato non significa è così che devi usarlo, anche se direi che qualsiasi evento che si verifica in un programma altrimenti immutabile è un cambiamento di stato.

I programmatori tendono ad essere ossessionati dall'essere "corretti". Non farlo. Alla fine della giornata, le definizioni delle parole non contano; ciò che conta è che il tuo programma funzioni.

    
risposta data 14.03.2015 - 15:31
fonte
1

Se non vuoi usare lo schema dell'osservatore, potrebbe esserci un altro modo. Mentre stavo leggendo la tua domanda, mi è venuta l'idea di usare il pattern Decorator .

Hai detto che non vuoi dare alla classe ConnectionFactory la responsabilità di impostare una variabile definita dall'utente nella sessione MySQL. Quindi, perché non decorare l'oggetto Connection con un oggetto esterno, diciamo MySqlConnection , che fa il lavoro sulla sessione MySQL al momento della creazione?

Una possibile soluzione potrebbe essere questa:

public class MySqlConnection extends Connection {
   // Decorated object
   private Connection connection;
   public MySqlConnection(Connection con) {
      this.connection = con;
      // Set the MySQL variable
      // ...
   }
   // Here you can redefine Connection methods if you need
   // to decorate some of them
}

public class ConnectionFactory {
   // ...
   public Connection makeConnection() {
      // Build a connection and then decorate it (code simplification)
      return new MySqlConnection(new Connection());
   }
}
    
risposta data 18.03.2015 - 21:42
fonte

Leggi altre domande sui tag