Incapsulamento di una singola proprietà

1

Se hai una singola proprietà che è rilevante in un progetto completo, ma dovresti logicamente avere solo una singola rappresentazione, come la rappresenteresti? Nel mio caso, sto sviluppando una semplice applicazione di disegno in cui l'utente può selezionare un colore. Questo colore dovrebbe quindi essere disponibile per tutte le classi penna / forma nel progetto.

Sarei semplice avere una classe statica con una proprietà statica di Color CurrentColor (C #), che ogni classe client potrebbe quindi chiamare, oppure esiste un modo più efficace?

    
posta Darren Young 24.12.2011 - 10:44
fonte

3 risposte

7

Entrambe le ipotesi ("il colore del disegno è necessario ovunque" e "dovrebbe esserci solo una singola istanza del colore del disegno corrente") sono false. Lasciatemi elaborare:

  • Gran parte del codice base non verrà influenzato dal colore corrente del disegno: pensa a cose come l'interfaccia utente (le parti che non sono direttamente correlate alla selezione del colore del disegno), la gestione del formato dei file di immagini (caricamento / salvataggio / conversione), routine di livello inferiore come mostrare finestre di dialogo aperte / file-salvate, ecc.
  • Puoi riutilizzare alcune funzioni relative ai disegni in un contesto diverso; anche se hanno una nozione di "colore del disegno corrente", si verificheranno presto dei problemi se il colore del disegno corrente è globale. Supponiamo di avere una routine che disegna un rettangolo su un'immagine; ora vuoi riutilizzarlo per implementare un filtro effetto che deve anche disegnare rettangoli. Se il colore del disegno corrente è globale, è necessario memorizzarlo in una variabile temporanea, modificarlo, disegnare il rettangolo e quindi reimpostarlo sul valore memorizzato. Questo è ingombrante e fragile, specialmente quando le operazioni di disegno possono essere asincrone. Un altro esempio potrebbe essere se è necessario gestire più immagini (qualcosa di MDI-ish, ad esempio) e si desidera tenere traccia del colore del disegno corrente per ogni immagine, indipendentemente. Se il tuo attuale colore di disegno è globale, imprecerai e imprecerai parecchio.

Personalmente, inserisco tutte le variabili di stato correlate (colore di disegno corrente, colore di sfondo corrente, modello corrente, ecc.) in una classe DrawingState (con la solita incapsulamento in posizione) e la passaggio esplicitamente a ciascuna operazione di disegno . In questo modo, si riduce la quantità di accoppiamento e il numero di potenziali modifiche allo stato e si aumenta la verificabilità dell'unità delle routine di disegno. In altre parole, il codice sarà più pulito, più facile da verificare, più facile da eseguire il debug e più facile da modificare.

    
risposta data 24.12.2011 - 12:59
fonte
2

Prima di tutto, è importante distinguere tra l'osservazione dalla testa leggera "Ne ho bisogno ovunque nel mio progetto" e "Ne ho bisogno in tutte le classi X del mio progetto", perché la prima porta a getter e singleton statici, e quest'ultimo alla corretta iniezione di dipendenza.

Ovviamente i singleton sono un'opzione, ma dal momento che creano praticamente variabili globali, preferirai preferire dipendenze atomiche esplicite.

Quindi non vuoi legare tutto il tuo progetto a una proprietà (anche se attualmente sembra una buona scelta). Vuoi accoppiare solo ciò che richiede l'accoppiamento, per definizione.

Nel tuo caso, ti suggerisco di creare una classe ColorSelection e una classe Toolbox (o qualcosa del genere) che passa il ColorSelection corrente a uno strumento appena selezionato. In altre parole, lo strumento Click handler (nella casella degli strumenti) imposterà la proprietà SelectedColor dello strumento sull'istanza definita (e associata) dalla casella degli strumenti.

Nel codice (molto impreciso, ma così ottieni il punto):

class ToolBox {
  ColorSelection SelectedColors {get; set;} // This could be bound to the view

  Tool Pen {get; set;}

  public event ToolEventHandler ToolSelected; // handled by the method below

  void ToolSelectedHandler(object sender, ToolEventArgs e) {
    e.Tool.SelectedColors = SelectedColors;
  }
    
risposta data 24.12.2011 - 11:16
fonte
1

Esistono situazioni molto vicine a zero assoluto in cui un progetto decente può legittimamente richiedere l'uso di una variabile globale. Le variabili globali sono pessime come quelle di goto, mai usate quelle.

La tua semplice applicazione di disegno dovrebbe avere una classe che rappresenta le "impostazioni attualmente selezionate". Un riferimento a questa classe dovrebbe essere passato al momento della costruzione in ogni singola classe che potrebbe averne bisogno. Quindi, ad esempio, il primo parametro del costruttore della classe penna deve accettare un riferimento alla classe "impostazioni attualmente selezionate", in modo che la penna possa recuperare il colore attualmente selezionato da esso, o qualsiasi altra cosa possa aver bisogno, come la penna spessore, opacità, solidità, passo, ecc.

La classe "impostazioni attualmente selezionate" dovrebbe anche avere un evento "Changed", al quale si abbonano tutti gli strumenti attualmente attivi, in modo che se l'utente cambia, per esempio, il colore corrente, la penna (o qualunque strumento sia selezionato) ) può prendere nota e recuperare il colore da esso.

    
risposta data 24.12.2011 - 12:29
fonte

Leggi altre domande sui tag