Il modo di implementare uno stile predefinito configurabile (in fase di esecuzione)

-1

Sto codificando un visualizzatore di algoritmi di grafi. Ogni vertice del grafico ha uno stile (colore, dimensioni, ecc.). Finché l'algoritmo non ha fatto nulla per un vertice, quel vertice ha uno stile predefinito . Lo stile predefinito deve essere configurabile in fase di esecuzione.

Mi è venuta in mente la seguente soluzione basata sullo schema del singleton, che mi sembra un po 'imbarazzante (come indicato nel commento). C'è uno migliore?

struct Style {
    int color;
    // size etc. are skipped for brevity
};

// Changeable default style
struct DefaultStyle {
    static DefaultStyle &instance() {
        static DefaultStyle res;
        return res;
    }
    DefaultStyle() = default;
    DefaultStyle(DefaultStyle const &) = delete;
    void operator=(DefaultStyle const &) = delete;

    Style s{5}; 
        // didn't see a benefit in making it private, 
        // since I would need to provide get() and set() anyways. 
};

int main()
{
    auto &s = DefaultStyle::instance().s; 
       // this need to access the style indirectly (.s) seems awkward

    s.color = 10;

    std::cout << DefaultStyle::instance().s.color << std::endl;
       // the change is globally visible
    return 0;
}
    
posta AlwaysLearning 04.03.2016 - 12:22
fonte

3 risposte

0

Cosa c'è che non va qui?

In primo luogo, lo scopo di un singleton è assicurarsi che una classe abbia una sola istanza e fornire un punto di accesso globale ad essa:

  • in effetti trarrai vantaggio da un punto di accesso globale allo stile predefinito per inizializzare lo stile dei nuovi vertici.
  • ma è necessario avere solo una sua istanza? Per esempio. non riesci a immaginare la tua applicazione con diverse finestre con diagrammi diversi, ognuno con uno stile predefinito diverso?

Quindi, lo "stile predefinito" è davvero un tipo / sottoclasse? Non è piuttosto un valore predefinito per le proprietà?

  • Immagina di avere classi di stile come Thick , Dotted , Blinking . Tutte queste classi avrebbero alcune proprietà comuni come color e brush_style .
  • Ora Blinking avrebbe bisogno di ulteriori informazioni sul duration di un lampeggio. In questo caso, non sarebbe sufficiente avere una singola classe di stile predefinita: avresti bisogno di tutti gli stili derivati da classi predefinite!

Come affrontare questo problema di progettazione

Secondo me, ci sono due approcci principali:

  • Prima opzione: se utilizzi un metodo fabbrica per creare forme e vertici, è sufficiente impostare il factory quando viene creato con lo stile predefinito (gestito dal valore o dal riferimento).
  • Seconda opzione: come vuoi utilizzare un oggetto per crearne di nuovi copiando prototype (es. stile di default), potresti anche pensare a un modello di prototipo di design

I due non sono incompatibili: se i tuoi stili non possono essere copiati banalmente (per esempio, se hanno alcune funzioni virtuali), o se potrebbero avere dimensioni diverse, la prima opzione dovrebbe avere il secondo per inizializzare lo stile del vertice.

    
risposta data 03.09.2016 - 00:56
fonte
0

Forse qualcosa di simile sarà più bello da usare. Il tutto potrebbe essere fatto da una variabile globale assegnabile, ma penso che sia ancora meglio avere un'interfaccia esplicita per questo.

struct Style {
    int color;
    // size etc. are skipped for brevity
};

// Changeable default style
struct DefaultStyle {
    static const Style &get() {
        return style();
    }
    static void set(Style s) {
        style() = s;
    }
    DefaultStyle(DefaultStyle const &) = delete;
    void operator=(DefaultStyle const &) = delete;
    DefaultStyle() = delete;
private:
    static Style& style() {
        static Style s{5};
        return s;
    }
};

int main()
{
    DefaultStyle::set({10});

    std::cout << DefaultStyle::get().color << std::endl;

    return 0;
}
    
risposta data 28.09.2017 - 11:30
fonte
-2

Ho perso una soluzione molto semplice: usare l'ereditarietà! Dopotutto, lo stile di default è uno stile!

struct Style {
    int color;
    // width etc. are skipped for brevity
};

// Changeable default style
struct DefaultStyle: Style {
    static DefaultStyle &instance() {
        static DefaultStyle res;
        return res;
    }
    DefaultStyle(DefaultStyle const &) = delete;
    void operator=(DefaultStyle const &) = delete;
private:
    DefaultStyle() = default;
};

int main()
{
    auto &d = DefaultStyle::instance();
    d.color = 10;
    std::cout << DefaultStyle::instance().color << std::endl;
    return 0;
}
    
risposta data 06.03.2016 - 14:01
fonte

Leggi altre domande sui tag