2016-04-28 50 views
11

Ho una simulazione che funziona a una determinata altezza ed una temperatura specifica:Quale modello di progettazione utilizzare per generare più simulazioni?

interface IGeneratable 
{ 
    string Name { get; } 
    void Generate(); 
}  

interface ISimulation : IGeneratable 
{ 
    int Height { get; } 
    int Temperature { get; }   
} 

Il processo Generate() per una simulazione in genere comporta più passaggi:

void Generate() 
{ 
    Step1(); 
    Step2(); 
    Step3(); 
} 

Ora, è possibile per l'utente per specificare più altezze e/o più temperature.

In questo caso, vengono generate diverse simulazioni (sub-simulazioni), una per ogni combinazione di altezza/temperatura. Metodo

interface IMultiSimulation : IGeneratable 
{ 
    ISimulation[] SubSimulations { get; }  
} 

Tuttavia, in questo caso, il sub-simulazione Generare() si discosta dall'ordine Step1, Step2, Fase 3:

  • Se vengono specificati più temperature, quindi Step2() deve essere eseguita solo una volta per tutte le sub-simulazioni, e non per temperatura (cioè una volta per multi-simulazione).
  • Se vengono specificati più altezze, quindi:
    • Step1() è pre-calcolate prima per tutti i sotto-simulazioni.
    • Vengono quindi eseguiti Step2, Passaggio3, ecc.
  • È possibile avere una simulazione grande con più altezze E più temperature. Ciò significa che 2 criteri di cui sopra devono essere soddisfatti. Note

generale

  • implementazione di un passo è incapsulato in IStep, che implementa IGeneratable. Quindi è possibile che una simulazione restituisca un elenco di passaggi, ad esempio.
  • Il numero di passaggi può essere piuttosto grande.

Ho cercato di utilizzare il modello di decoratore ma senza successo.

Sto cercando uno schema corretto con una soluzione scalabile che gestisca la generazione di una singola simulazione e di più simulazioni.

Grazie.

+1

Un'interfaccia di simulazione che astrae una o più simulazioni, suona come un [Composito] (https://sourcemaking.com/design_patterns/composite). – jaco0646

risposta

0

la sua mi sembra c'è un caso d'uso molto specifico per implementare così vi suggerisco di utilizzare una classe che includerà imlementation per Generare() (spero ho capito i requisiti destra)

class Simulation 
{ 
    string Name { get; } 
    int[] Heights { get; } 
    int[] Temperatures { get; } 

    void Generate() { 
     for (int i = 0; i < Temperatures.Count; i++) { 
      for (int j = 0; j < Heights.Count; j++) { 
        GenerateStep1(); 
      } 
      GenerateStep2(); 
      GenerateStep3(); 
     } 
    } 
} 
+0

Non funzionerà perché GenerateStep2() dovrebbe essere eseguito una sola volta. – alhazen

1

Nella tua caso, vorrei utilizzare il composito del modello di progettazione. Il metodo di generazione controllerebbe che abbia componenti. In caso contrario, chiamerà semplicemente

void Generate() 
{ 
    Step1(); 
    Step2(); 
    Step3(); 
} 

ma se ha componenti significa che ha più simulazioni.Poi il codice sarà qualcosa del tipo:

void Generate() 
{ 
if(this.simulations.Count==0) 
{ 
    Step1(); 
    Step2(); 
    Step3(); 
} 
else 
{ 
    if(multipleHeights) 
    { 
     precomputeStep1(); 
     if(multipleHeights) 
     { 
     createSingletonForStep2(this); 
     } 
     else 
     { 
     Step2(); 
     } 
     Step3(); 
    } 
    } 
} 

E per la fase 2 Vorrei semplicemente chiamare un Singleton che riceve questo composto come parametro, quindi per questo gruppo di simulazioni ci sarà solo uno Step2.

1

Interfacce:

interface IGeneratable 
{ 
    string Name { get; } 
    void Generate(); 
} 

interface IGeneratableOnce : IGeneratable 
{ 
    bool HasRunned { get; set; } 
} 

interface ISimulation : IGeneratable 
{ 
    int Height { get; } 
    int Temperature { get; } 
    IMultiSimulation MultiSimulation{ get; } 
    IGeneratable[] Steps{ get; } 

} 

interface IMultiSimulation : IGeneratable 
{ 
    ISimulation[] SubSimulations { get; }  
} 

tipica MultiSimulation generate:

void Generate(){ 
    for (ISimulation simulation in SubSimulations){ 
     simulation.Generate(); 
    } 
} 

ISimulation tipica generate:

void Generate(){ 
    for (IGeneratable step in Steps){ 
     step.Generate(); 
    } 
} 

ISimulation Generare evitando seconda manche Fase due volte:

void Generate(){ 
    for (int i=0;i<Steps.Length;i++){ 
     IGeneratable step = Steps[i]; 
     if (i!=1){ 
      if (step is IGeneratableOnce && !(step as IGeneratableOnce).HasRunned){ 
       step.Generate(); 
       step.HasRunned = true; 
      } 
     }else{ 
      step.Generate(); 
     } 
    } 
} 

È possibile aggiungere alcuni altri flag, se lo si desidera, forse anche una sorta di metodo come CanRun (int Height, int Temperature) nel caso in cui la logica diventi troppo complessa. Tuttavia, nella tua situazione, credo che dovresti usare una variazione di pattern composita come questo esempio di codice.

EDIT: Here un altro modello interessante che si può utilizzare

1

Il vostro compito non è così piccolo, quindi la risposta è non un singolo modello di progettazione, ma invece multipla. Personalmente non enfatizzerei gli schemi, ma piuttosto l'implementazione intuitiva e intenzionalmente rivelatrice (ad esempio ne ho scritto qui: http://www.tutisani.com/software-architecture/intuitive-object-models.html). Penso che il tuo design non sia intuitivo e auto-descrittivo, quindi non stai risolvendo il problema giusto ponendo la domanda che hai posto.

In ogni caso, dal momento che stai chiedendo di identificare gli schemi di progettazione, ti aiuterò anche in questo.

  • Fatto che tutti i tipi derivati ​​(in particolare le interfacce) implementano IGeneratable, ovvero il modello di progettazione Super Type.
  • Come alcuni suggeriscono, la simulazione contenente altre simulazioni all'interno è uno schema Composite. Tuttavia, non è del tutto accurato poiché IMultiSimulation non implementa l'ISimulation. È comunque una specie di composito, perché sia ​​i genitori che i bambini implementano almeno IGeneratable.
  • IStep suona come uno schema Strategy, ma suppongo che non lo stai implementando correttamente.

Ora, voglio suggerirvi di ripensare il vostro approccio al design, perché le vostre interfacce non sono intuitive. Ecco i problemi che vedo, che è necessario ripensare:

  • L'ISimulation ha Altezza e Temperatura e ha anche Genera(). Generate() molto probabilmente dovrebbe usare Altezza e Temperatura - è così che ho capito la vostra descrizione, ma poi non è il modo giusto per esprimerlo. Se Genera() dipende da Altezza e Temperatura, quindi passali come argomenti e non definirli come proprietà. Inoltre, l'interfaccia può esprimere meglio il comportamento, non lo stato. Le proprietà rappresentano lo stato, che esprimerei come classe, non come interfaccia.
  • Se la simulazione sta per eseguire dei passaggi, non definirli sulla stessa ISimulation, che di nuovo non è un design così intuitivo.Passali come argomenti, e questo lo renderà un modello di progettazione della strategia (ecco perché ho detto sopra che non è implementato correttamente).

Vorrei andare oltre, ma non conosco l'intera immagine. Da quello che hai espresso, la tua implementazione presentata non è corretta. Per favore ripensaci.