metodo per permettermi di modificare liberamente le mie classi, ma renderle immutabili per gli altri?

5

Sto creando la parte del modello di un'architettura MVC. La mia unica classe fornirà tutti gli accessi per consentire a uno di recuperare lo stato del sistema. Voglio che la maggior parte di questo stato sia immutabile in quanto non dovrebbe essere modificato e non voglio che nessuno acceda al mio modello per poter violare lo stato facendo un cambiamento folle.

Tuttavia, gli oggetti che rappresentano lo stato hanno un po 'di struttura ad albero. l'oggetto A contiene un insieme di B che contiene un insieme di oggetti C che contengono un insieme di oggetti D ecc. ecc. Data la natura di come devo recuperare i dati, non posso costruire la struttura dal basso verso l'alto; la parte più bassa dell'oggetto "chid" verrà generata dopo che tutte le altre sono state completate. Questo rende piuttosto scomodo costruire gli oggetti immutabili in modo intuitivo, voglio aggiungere un set come ultima fase di costruzione ma non posso se ho già creato oggetti immutabili.

Conosco tre approcci, ma non sono sicuro che mi piacciano. Uno è un costruttore patern, ma tenere traccia di tutti i costruttori per una struttura complicata finché non ho finito sembra che potrebbe essere molto brutto. In secondo luogo è di avere una sorta di metodo "clone" che costruisce un nuovo oggetto immutabile clonando il vecchio ma aggiungendo un nuovo set ad esso fornito (come viene chiamato di nuovo questo modello?). Questo diventa brutto quando provo ad aggiungere al figlio la maggior parte degli elementi del set dato che ho bisogno di ricostruire praticamente l'intero albero con 'nuovi' oggetti immutabili per aggiungere un valore.

La terza soluzione, finora la più semplice, è quella di eliminare la struttura ad albero e farli chiamare al mio modello per ottenere i dati desiderati. così invece di chiamare myObject.getChildren chiamano Model.getObjectChildren (myObject). Questo funzionerà, ma accidenti volevo la bella struttura ad albero per il mio stato immutabile.

C'è un altro modo per costruire comodamente il mio stato in un modo in cui il mio modello può modificare liberamente lo stato mentre viene costruito; ma è ancora immutabile quando è finalmente pubblicato sul Controller?

ps. Sto correndo in java se questo è importante.

    
posta dsollen 26.03.2013 - 20:28
fonte

2 risposte

4

Vorrei usare le interfacce per questo:

interface ReadOnlyA {
    public ReadOnlyB getB();
    ...
}

interface ReadOnlyB {
    ...
}

class A implements ReadOnlyA {
    private B b;
    public B getMutableB() {
        return b;
    }
    public ReadOnlyB getB() {
        return getMutableB();
    }
    public void setB(B newB) {
        b = newB;
    }
}

In sostanza, un'interfaccia per classe che implementa solo metodi di sola lettura e restituisce solo le istanze delle interfacce di sola lettura per altri oggetti; ma tu usi gli oggetti delle classi effettive (mutevoli) internamente. Credo che questo sia simile all'idea di capacità --- un riferimento all'interfaccia equivale a una capacità di "lettura", ma i riferimenti interni alle classi sono capacità di 'scrittura' (e 'scrittura di oggetti contenuti').

    
risposta data 27.03.2013 - 22:00
fonte
6

Certo che è possibile. Alcuni ne hanno anche coniato un termine: Popsicle immutable . L'idea generale è di avere una struttura di dati mutabile all'interno, oltre a un flag che indica se l'oggetto è attualmente mutabile o meno. Nota che in molti casi (incluso questo), vuoi solo che il flag passi da "mutable" a "immutable" una volta, e mai dall'altra parte. Quindi aggiungi semplicemente

  1. Metodi per mutare lo stato, che controlla il flag e genera un errore se l'oggetto non è mutabile.
  2. Un metodo per capovolgere la bandiera e quindi rendere l'oggetto immutabile. Questa è anche una buona opportunità per eseguire alcune ottimizzazioni (ad esempio tagliare la capacità in eccesso delle raccolte o creare un indice), come ora sai che lo stato non cambierà.

Questo aggiunge una certa complessità all'implementazione e alcuni potenziali errori (dimenticando di capovolgere l'interruttore, cercando di mutare un oggetto immutabile). Ma questo è inerente a questa abilità. Per riguadagnare un po 'di semplicità, puoi disabilitare operazioni non legate alla costruzione dello stato mentre l'oggetto è mutabile. Ciò significa che hai meno casi da supportare / preoccupare.

    
risposta data 26.03.2013 - 20:53
fonte

Leggi altre domande sui tag