Passare una raccolta di membri privati in un'altra classe

4

Supponiamo di avere una mappa che è una variabile membro privata della mia classe A.

Nella stessa classe creo un'istanza di classe B, chiamiamola objB, passando la mappa al costruttore di B.

Ovviamente questo è sbagliato, perché ho fatto trapelare un campo privato a un oggetto di una classe diversa. Quella classe potrebbe in seguito decidere di modificare la mappa passata, cosa che rovinerebbe tutto.

È preferibile 1) passare usando Collections.unmodifiableMap o forse 2) copiandolo? Se c'è un altro approccio migliore, sarei felice di vederlo.

Nel caso in cui la mappa venga modificata in classe A, objB dovrebbe conoscere immediatamente la nuova mappa. E questo significa che dovrei aggiornare la mappa in objB ogni volta che la modifico (ma non se la passo ad una lista non modificabile).

Penso che l'opzione 2 sia migliore, perché in 1) passiamo una raccolta non modificabile a B, e B assume che le collezioni passate siano modificabili.

class A {
    Map<String, Integer> map;

    public A() {
        map = new HashMap<String, Integer>();
        B objB = new B(map); //option 1
        B objB = new B(Collections.unmodifiableMap(map)); //2
        B objB = new B(new HashMap(map)); //3
    }
}

class B{
    Map<String, Integer> map;

    public B(Map<String, Integer> map) {
        this.map = map;
    }

    //use data from the map to do stuff
}
    
posta user4205580 21.05.2016 - 19:45
fonte

3 risposte

4

In case the map is modified in class A, objB should know the new map immediately.

Se per conosci immediatamente vuoi dire assumere immediatamente lo stesso stato senza fare nulla al riguardo allora B dovrebbe semplicemente tenere un riferimento alla mappa. Puoi proteggerlo con una mappa non modificabile. Questo approccio non è multi-threaded friendly poiché A è ancora libero di mutare la mappa quando B potrebbe attraversarlo.

Se per conosci immediatamente intendi gestire il cambiamento di stato in qualche modo poi usa il schema di osservazione . B è un osservatore dello stato di A. Quando A cambia stato dovrebbe notificare a tutti gli osservatori. In questo modo A non è costretto a esporre il suo riferimento alla mappa per tenere aggiornato B.

Probabilmente sarebbe una buona idea leggere su immutabilità e coping difensivo .

    
risposta data 21.05.2016 - 21:03
fonte
0

Se B ha bisogno di cercare all'interno dei dati di A, allora dovrebbe usare l'interfaccia pubblica di A per farlo.

    
risposta data 22.05.2016 - 14:52
fonte
0

Penso che la tua domanda rimandi alla mancanza di comprensione del problema del dominio che stai cercando di risolvere.

  • Se hai due oggetti A e B e B vuole sapere qualcosa da A , dovrebbe semplicemente chiedere .

  • Se B vuole mutare A s stato, dovrebbe chiedere A di farlo.

Hai solo bisogno di una connessione tra entrambi gli oggetti, ad es. tramite composizione o come parametro quando si chiama B per fare qualcosa.

Obviously this is wrong

Sì. Rompe l'incapsulamento.

If there's another, better approach, I'd be glad to see it.

C'è: per es. B.doFreakyStuffWith(A)

    
risposta data 22.05.2016 - 19:21
fonte

Leggi altre domande sui tag