Come memorizzare oggetti con proprietà incoerenti

2

Ho materiali del mondo reale che sono definiti da varie proprietà, alcune comuni, altre no, che mi piacerebbe mappare agli oggetti in C #. Ad esempio, Concrete ha proprietà A , B , C e Metal ha proprietà A , B , D , E .

Questo sembra un caso da manuale per l'ereditarietà della classe:

class Material
{
    public double A { get; set; }
    public double B { get; set; }
}
class Concrete : Material
{
    public double C { get; set; }
}
class Metal : Material
{
    public double D { get; set; }
    public double E { get; set; }
}

Questo potrebbe funzionare per il momento, tuttavia, tenendo presente la manutenibilità del codice, posso pensare ad alcuni avvertimenti: il codice esegue calcoli secondo uno standard dato, ma nel gioco finale, dovrebbe essere adattabile ad altri standard, che può richiedere proprietà diverse all'oggetto, o addirittura modificare la caratterizzazione dell'oggetto (classi derivate). Questo porterebbe a qualcosa di simile:

class Material
{
    public double A;
    public double B;
}
class Concrete : Material
{
    public double C;
}
class Metal : Material
{
    public double D;
    public double E;
}
class Concrete_US : Material
{
    ...
}
class Metal_US : Material
{
    ...
}
class Concrete_Europe : Concrete
{
    ...
}
class Steel_Europe : Metal
{
    ...
}
class Copper_Europe : Metal
{
    ...
}

Bene, questo sta iniziando a diventare disordinato. Ma peggio ancora, un dato materiale può benissimo essere completamente caratterizzato su più standard, quindi un oggetto potrebbe dover essere un'istanza di più classi.

Quindi attualmente sto usando un altro approccio, che è quello di avere un Properties dictionnary, associando stringhe ai valori in una singola classe Material . In questo modo, il supporto di un nuovo tipo di materiale e / o di uno standard è solo una questione di aggiungere voci di dizionario. Tuttavia, questo si sente soggetto a errori, con rischi di collisioni e errori di battitura (anche la manipolazione delle stringhe è inefficiente, ma non ci sono molti accessi al dizionario).

C'è un modo migliore per farlo?

    
posta gazoh 11.12.2018 - 18:17
fonte

3 risposte

5

Non cercare di creare oggetti che simulano gli equivalenti del mondo reale

Crea oggetti che contengono dati che corrispondono ai loro metodi

Nel tuo esempio di materiali, in realtà non dici per cosa vengono utilizzati i dati.

Se per esempio hai una funzione Compress(Material) , allora avrai bisogno di Material.CompressibilityFactor . È possibile definire un'interfaccia:

public interface ICompressible
{
     double CompressibilityFactor {get}
}

Questo non significa che le cose che non ereditano da ICompressible sono fisicamente incomprimibili. Significa che la funzione nel tuo codice non può operare su di essi.

Se hai solo bisogno di memorizzare proprietà casuali e poi visualizzarle, il metodo del dizionario, se necessario, non ha funzioni che richiedono proprietà specifiche

    
risposta data 11.12.2018 - 19:42
fonte
3

Sembra un caso da manuale per l'ereditarietà. Sfortunatamente la maggior parte dei libri di testo non menziona l'ereditarietà, spesso non è la scelta migliore. Come hai notato, puoi creare rapidamente un albero ereditario gigante e disordinato con un sacco di codice duplicato. Il principio della composizione sul diritto ereditario potrebbe essere applicato qui. Sfortunatamente non hai dato molti dettagli su cosa dovrebbero fare le tue classi, ma potrebbero avere comportamenti come IBendBehavior, IMeltBehavior, ICompressBehavior, ecc. Successivamente creerai varie implementazioni per queste interfacce, con i loro calcoli distinti. Finalmente applichi le implementazioni specifiche ai tuoi oggetti. Puoi anche cambiare le implementazioni in runtime, consentendo ai tuoi clienti di creare materiali completamente nuovi con i comportamenti che scelgono.

    
risposta data 11.12.2018 - 20:16
fonte
3

Prova un Sistema componenti Entity .

Questa tecnica prende la prospettiva che non sappia come apparirà una Entità in fase di esecuzione. Sei già a metà strada con il tuo sistema di borsa di proprietà, che non è un cattivo modo per gestire l'ignoto. Il problema è che queste proprietà non sono sconosciute, semplicemente non sai quali entità avranno il loro insieme.

Questo è dove l'aspetto Componente brilla. Ogni componente può definire un set completo di proprietà richieste, anche dichiarando una dipendenza da altri componenti che fanno parte dell'entità.

Infine il Sistema fornisce un modo per gestire ciascun componente in modo scalabile. Fornisce un modo gestibile per mettere a punto il sistema, modificare il comportamento in fase di esecuzione e adattarsi perfettamente ai loop di simulazione.

Diverse altre proprietà piacevoli escono da questo sistema per includere:

  • serializzazione
  • gestione della memoria
  • extensability
  • riconfigurabilità
  • modelli di script

Ovviamente potresti non aver bisogno di un sistema di componenti Entity completo, in tal caso dai un'occhiata a Mixins .

    
risposta data 12.12.2018 - 01:41
fonte

Leggi altre domande sui tag