Design Pattern per mitigare le conversioni non banali di tipi definiti dall'utente

-1

Sfondo

Ho creato un Template Factory class il cui compito è quello di restituire std::function oggetti, creati da static funzioni per usare il pattern Decorator per DI in una classe stateful. Diciamo, per un momento, che il class che sto scrivendo, è chiamato Currency , e invece di avere Dollars : Currency , Yen : Currency , ecc., Invece ho ogni Currency class contenere un enum class CurrencyType membro.

Problema

Dato l'esempio sopra, diciamo che devo convertire da Yen a Dollars . Considera la seguente struttura di classe (vai alla sezione seguente per il problema reale):

// Currency.h
struct Currency {
    // ... fluff code
    double value; // precision is not the scope of this question
    CurrencyType type;
    Factory factory; // for mocking & unit tests, pretend this uses template method pattern
    void convert(CurrencyType newType){
        value = factory.convert(type, newType)(value);
    }
};

// Factory.h
struct Factory {
    std::function<double(double)> convert (CurrencyType from, CurrencyType to){
        if (from == to){
            return [](double d){return d};
        } else if (from == Yen && to == Dollars){
            return &convertCurrency<Yen, Dollars>;
        } else if (from == Dollars && to == Yen){
            return &convertCurrency<Dollars, Yen>;
        } // possibly throw exception, out of scope of this question
    }
};

// ConvertCurrency.h

template <CurrencyType, CurrencyType> struct Yen_to_Dollars : std::false_type{};
template <> struct Yen_to_Dollars<CurrencyType::Yen, CurrencyTyoe::dollars> :
    std::true_type{};

template <CurrencyType from, CurrencyType to>
typename std::enable_if<Yen_to_Dollars<from, to>::value, double>::type
constexpr convertCurrency(const double currency){
    return // implementation of function
};

Man mano che il numero di CurrencyType s aumenta, il numero di istruzioni if dovrà essere supportato crescerà esponenzialmente. Dal momento che non esistono abbreviazioni per mappare solo le enumerazioni di runtime su constexpr , quali sono le mie opzioni per quanto riguarda la progettazione di classi? Sicuramente l'ereditarietà non aiuterebbe neanche, poiché ogni classe derivata dovrebbe implementare alcuni metodi di conversione simili. Ho considerato di ereditare Currency con CurrencyType come parametro di tipo, ma avrei bisogno di un mezzo di conversione tra di loro, ancora una volta probabilmente adatto per un adattatore.

Sebbene le fabbriche siano generalmente i posti in cui concederemo un po 'di margine per le dichiarazioni di stile caso di commutazione più lunghe (specialmente con le enumerazioni), mi chiedevo se esistessero soluzioni alternative a quello che sto cercando di ottenere. Chiaramente questo M x N numero di definizioni non risolve il mio problema originale e in effetti crea di più. Sentiti libero di commentare con qualsiasi soluzione / conseguenze impreviste, in quanto mi piacerebbe poter confrontare i potenziali costi di manutenzione.

Pensieri aggiuntivi

  • La valuta è uno scenario esemplificativo (certamente un po 'forzato, poiché le valute cambiano spesso di valore più volte al giorno), ma il mio esempio vale per qualsiasi conversione statica. Pensa a qualsiasi tipo di oggetto convertibile, come piedi per metri, da Celsius a Fahrenheit, da ore a minuti, ecc.
  • Mi aspetto che il mio problema principale derivi dal punto di vista del design, poiché, sebbene si possa sostenere che sostituisce ogni abilitazione se con una versione più leggibile e qualificata, come convertYenToDollars , la ripetizione esiste quindi nel nome in opposizione ai parametri di tipo (Strawman IMO)
  • L'utilizzo di un modello di adattatore attenuerebbe lo scenario molti a uno, tuttavia potrebbe non essere sempre possibile, dato che anche la definizione di un CurrencyType predefinito probabilmente non sarebbe decidibile fino al runtime.
  • Non sono sicuro che CurrencyType debba essere completamente diverso o meno. Un problema particolare che mi capita di avere è che diciamo che il NYSE alimenta tutti i dati in dollari, e vogliamo solo convertire le azioni con base in Giappone Yen, dove le impostazioni locali dell'utente possono essere impostate su Pesos. Dovrebbero i dollari - > Yen - > I pesi creano 3 nuovi oggetti?
  • Una possibile struttura di ereditarietà dei modelli potrebbe giocare abbastanza bene con la funzione di fabbrica, in quanto avrei solo bisogno di creare funzioni di conversione M + N per l'adattatore e potrei fare a meno dei tratti di carattere sgradevole.
posta jfh 20.12.2018 - 21:59
fonte

0 risposte

Leggi altre domande sui tag