Memento per la classe ereditata

0

Ho la seguente domanda.

Ho una classe astratta che gestisce gli elementi grafici. Chiamiamolo GraphicHost. Qualcosa del genere:

class GraphicHost {
    class GraphicHostState {
        List<Sprite> sprites;
        List<Text> texts;
    }

    GraphicHostState state;
    public void setState(GraphicHostState s);
    public GraphicHostState getState();

    public void addSprite(Sprite s);
    public void addText(Text t);    
}

Ho bisogno di salvare e ripristinare lo stato mentre mi muovo da una scena all'altra, quindi sottoclasse di stato.

Ora ho un'implementazione concreta che utilizza, diciamo, OpenGL. Chiaramente, oltre allo stato di base, avrò bisogno anche delle maniglie degli shader e delle trame, ecc.

Sarà una buona soluzione ereditare GraphicHostState e aggiungerli lì? Come:

...
class GLGraphicHostState {
    List<Integer> textures;
    List<Integer> shaders;
}
...

Il problema è che l'oggetto host grafico deve essere polimorfico. Ho ScriptHost che usa l'host grafico per aggiungere sprite / testi, e non dovrebbe conoscere l'implementazione concreta, ma dovrebbe essere in grado di salvare e ripristinare il suo stato. Posso sovrascrivere getState / setState , ma poi in setState dovrò verificare se lo stato fornito è GLGraphicHostState , e questo controllo sembra un un po 'disordinato, come una soluzione alternativa.

Quindi, in generale, come suggeriresti di farlo se ho una classe astratta con qualche stato, classe figlio con parametro di stato aggiuntivo e lo stato deve essere salvato / ripristinato in modo polimorfico (tramite l'interfaccia grafica di GraphicHost)?

Per quanto ho capito, il pattern di Memento si adatta alla situazione in cui lo stato deve essere salvato e ripristinato, ma come faccio ad adattarlo alla gerarchia di classi come quella di cui sopra?

    
posta olegst 03.07.2018 - 10:10
fonte

1 risposta

2

Sento che il tuo intero approccio è fuorviato qui. Come conosco C # meglio di Java, esprimerò il codice usando il primo. Ma alcune idee generali si applicano anche ad altre lingue.

In primo luogo, non c'è un reale bisogno di una classe astratta qui. Quindi usa un'interfaccia:

interface IGraphicHost 
{
    GraphicHostState State { get; set; }
    void addSprite(Sprite s);
    void addText(Text t);    
}

Quindi dobbiamo affrontare il problema che le diverse implementazioni richiedono versioni diverse di GraphicHostState . Opterei per una delle due alternative per affrontare questo:

Opzione 1: utilizza i generici

interface IGraphicHost<TState> where TState : IGraphicHostState
{
    TState State { get; set; };
    public void addSprite(Sprite s);
    public void addText(Text t);    
}

Quindi ora ogni implementazione di IGraphicHost fornisce quindi la propria implementazione di IGraphicHostState , ad esempio:

class GLGraphicHost : IGraphicHost<GLGraphicHostState>
{
    ...
}

Opzione 2: chiedi alla classe di gestire il proprio salvataggio e caricamento dello stato

interface IGraphicHost
{
    void SaveState(Stream stateStream);
    void RestoreState(Stream stateStream);

    public void addSprite(Sprite s);
    public void addText(Text t);    
}

Quindi ora la classe viene fornita con uno stream a cui può leggere e scrivere il proprio stato. Come si presenta questo stato e come viene caricato e salvato diventa quindi la responsabilità della classe senza il bisogno di GraphicHostState .

    
risposta data 03.07.2018 - 11:46
fonte

Leggi altre domande sui tag