Ereditarietà: quando solo alcuni oggetti concreti devono condividere lo stato

2

Ho una serie di classi che rappresentano i widget in un sistema di layout. La classe base per tutti questi tipi di widget concreti è Widget . Se ho un pulsante e una casella di testo, entrambi derivano da Widget .

Il layout è strutturato come un albero. Ogni widget può avere solo 1 genitore e zero o più figli, che sono anche di tipo Widget .

Alcuni di questi tipi di widget concreti devono condividere lo stato. Come esempio, diciamo che ogni widget determina il proprio colore di sfondo da un elenco di colori predeterminati, configurato dall'utente chiamato Theme . Il tema generale dell'applicazione consente di definire i colori per ampie categorie di widget. Quando un widget deve sapere quale dovrebbe essere il suo colore di sfondo, ha bisogno di accedere attivamente alla stessa istanza di Theme per effettuare la ricerca. Quindi, quello che trovo sono alcuni widget nel sistema (quelli che possono essere colorati, come il pulsante e la casella di testo) che richiedono l'accesso a un'istanza Theme , ma ad altri widget non interessa il colore.

L'opzione 1 è fare in modo che il costruttore di Widget prenda un riferimento al Theme , che le sottoclassi possono scegliere di usare temporaneamente, memorizzare in modo permanente (per uso continuato), o non usare affatto. Il lato negativo di questo è che non tutte le sottoclassi dei widget si occupano dei temi, quindi è come avere una classe "Ostrich" derivata da una classe "Bird" con una funzione chiamata "Fly ()" (cioè non tutti gli uccelli volano).

L'opzione 2 è quella di utilizzare il modello visitatore. Dopo la costruzione di tutti i widget, usa lo schema visitatore con le sostituzioni per Button e TextBox per ottenere lo stato dall'oggetto visitatore per fare ciò che deve fare. Altri tipi di widget sarebbero "predefiniti" a non attivi nella classe visitatore avendo un terzo sovraccarico che prende il tipo di base Widget .

C'è un'opzione 3 che è meglio? Qualche idea sulle 2 opzioni sopra? Qual è l'approccio giusto qui?

    
posta void.pointer 08.11.2018 - 21:54
fonte

4 risposte

2

La tua opzione 1 è probabilmente la soluzione migliore qui. Cerca di non pensarlo come un Widget che non usa Theme tanto quanto ha un Widget che è "a tema", ma in realtà non cambia aspetto come conseguenza.

Forse non è così "carino" come vorresti che fosse, ma considera cosa significa questo dal punto di vista della manutenzione. Se in un secondo momento decidi che una particolare istanza Widget effettivamente fa richiede un po 'di themall, non dovrai fare altro che correggere direttamente Widget per usare l'istanza Theme . L'aggiunta di nuove configurazioni Theme è semplicemente una questione di modifica di Theme e quindi di utilizzo delle nuove proprietà in Widget .

Questo è in aggiunta all'azione già necessaria per trasportare l'istanza da utilizzare dai figli del tuo widget, che se non altro devi tenerla perché non dovresti mai presumere che i figli della tua Widget non richiederanno un'istanza Theme .

Se ritieni che questo non sia adeguato, puoi sempre creare un'interfaccia ThemedWidget e avere tutte le classi che utilizzano Widget per derivare da quello. Ma a questo punto, estendere direttamente da Widget e non ThemedWidget significa che non può trattenere i bambini che usano il tema. Potrebbe essere utile da una prospettiva purista, se non si ritiene che cambierà probabilmente nel prossimo futuro.

    
risposta data 09.11.2018 - 11:14
fonte
2

Il problema con l'opzione 1 è che stai abbinando il "tema" al widget. I temi applicativi possono diventare molto complicati e disordinati man mano che nuove funzionalità vengono aggiunte al sistema, quindi potrebbe essere utile disaccoppiare il "tema" dal widget. Per questo ti consigliamo di utilizzare il modello di fabbrica:

  1. Rimuovi tutti i riferimenti al codice del tema da tutte le tue classi di widget
  2. Crea una nuova classe chiamata WidgetFactory
  3. Passa un tema al costruttore di WidgetFactory per disaccoppiare la costruzione della fabbrica dal tema
  4. Esporre 1 metodo pubblico per widget che crea semplicemente un nuovo widget di quel tipo

    Internamente, questi metodi pubblici sanno come costruire un nuovo widget e passare le corrette impostazioni del tema per configurare il widget.

  5. Qualunque "proprietà" della fabbrica di widget dovrebbe anche "possedere" il tema in modo che la memoria non perda.

Sono un po 'di luce sull'esperienza C ++, e questo prossimo bit dovrebbe essere verificato da qualcuno più esperto di me, ma qualunque cosa stia chiamando la fabbrica di widget per generare un elemento dell'interfaccia utente dovrebbe quindi assumere la proprietà o la responsabilità di gestire quella memoria, non la fabbrica di widget.

La responsabilità della fabbrica di widget dovrebbe essere la creazione di widget e il loro matrimonio con le impostazioni nel tema senza che i widget conoscano il tema. Ciò ti dà la possibilità di ridefinire il tema in modo che corrisponda alle mutevoli esigenze di business senza dover refactoring un'intera gerarchia di classi di widget dell'interfaccia utente nel processo e consente di ridefinire le classi del widget senza toccare il tema.

    
risposta data 09.11.2018 - 14:16
fonte
0

La mia inclinazione sarebbe quella di creare un widget Widget discendente che si preoccupa del suo aspetto. Questo potrebbe fare riferimento a un oggetto Tema statico. Sarebbe appropriato che il tema fosse statico perché ce n'è solo uno per tutti in un determinato momento.

Questo lascerebbe i normali widget inconsapevoli e indipendenti dai contenuti estetici e permetterà a quelli che hanno bisogno di fare qualche aggiustamento per farsi strada con i dati del tema.

La tua fabbrica di widget dovrebbe conoscere il nuovo tipo di widget e crearlo come appropriato. Potrebbe anche passare i dati del tema a quel punto, al momento della costruzione. Quindi non avresti bisogno di un tema statico, potresti semplicemente passare un'interfaccia ITheme al costruttore di ThemedWidget.

    
risposta data 09.11.2018 - 14:54
fonte
0

Potresti pensare di usare uno schema Observer o Notifier . I widget che devono conoscere i temi possono essere abbonati ai cambiamenti del tema (l'oggetto osservabile). Ogni volta che il tema cambia, l'osservatore viene informato del cambiamento, eventualmente inviando il nuovo tema. Per renderlo generale (potrebbe non essere possibile inviare un oggetto Theme ), puoi pensare a un formato di configurazione, non solo per i temi, forse un oggetto JSON (essenzialmente solo una stringa), che potrebbe anche essere usato per notificare ad altri oggetti le modifiche che potrebbero dover prendere in considerazione.

    
risposta data 09.11.2018 - 21:20
fonte

Leggi altre domande sui tag