Il modello di strategia non è sufficiente per il mio problema?

3

Lasciatemi abbozzare la situazione:

  • Ho più utenti, con determinate proprietà (2 enumerazioni)
  • Per ogni utente ho bisogno di recuperare i dati, per alcuni con alcuni filtri di base, per alcuni filtri estesi (= filtro di base + filtro aggiuntivo). Mi piacerebbe farlo non separato per ogni utente, ma preferirei raggruppare gli utenti e farlo in due query.
  • Per ogni utente, ho bisogno di filtrare i dati in base ai valori dell'enumerazione. sempre devo fare GetFirstData() (metodo che dipende dal primo enum), GetLastData() (metodo che dipende dal secondo enum), CheckData() (dipende da entrambe le enumerazioni).

Ho esaminato il Pattern di strategia , ma sembra che sia più progettato per implementare un comportamento. Voglio combinare i miei comportamenti per evitare di creare le combinazioni tra tutti GetFirstData e GetLastData , c'è qualche schema per farlo meglio? Ho pensato solo a usare 2 delegati e assegnare i metodi corrispondenti in base ai valori delle enumerazioni . Questo sarebbe il modo più pulito?

Piccolo esempio di cosa intendo:

public class User
{
   public Enum1 FirstEnum {get; set;}
   public Enum2 SecondEnum {get; set;}
   ...
}
public IEnumerable<Data> Filter(int userId, Expression extraFilter)
{
    var data = GetData(userId);
    if(extraFilter != null)
      data = data.Where(extraFilter);
    return data;
}
public Data GetFirstData(IEnumerable<Data> data);
public Data GetLastData(IEnumerable<Data> data);
public bool CheckData(IEnumerable<Data> data);

Il mio endresult potrebbe fare qualcosa del genere:

public class EndResult
{
    public Data FirstResult {get; set;}
    public Data SecondResult {get; set;}
    public Func<IEnumerable<Data>,Data> GetFirstData {get; set;}
    public Func<IEnumerable<Data>,Data> GetLastData {get; set;}
    public bool ExtendeFiltering {get; set;}

    public EndResult(User user)
    {
        switch(user.enum1)
        {
            case: GetFirstData = specificFunction;
                  ExtendedFiltering = true;
            ...
        }
        //Second for GetLastData;
    }

    public void Execute()
    {
        GetData();
        CheckData();
        GetFirstData();
        GetLastData();
    }
}

Modifica: per i futuri lettori che sono curiosi, non ho usato i delegati (almeno non direttamente). Ho creato 2 interfacce IFirst e ILast con un metodo corrispondente. Nel mio metodo di creazione statico definito sulla mia classe di processore, eseguo la logica per creare un'istanza di tali interfacce in base a determinate condizioni. Il motivo per cui ho lasciato il percorso usando direttamente i delegati è perché ho scoperto che avevo bisogno di più parametri rispetto a User per alcuni di essi. Così ho fatto ricorso a diverse implementazioni basate sui parametri che ho bisogno nel costruttore di quelle classi.

    
posta Alexander Derck 01.03.2016 - 10:38
fonte

1 risposta

6

Utilizzare i delegati nel modo suggerito è una forma specifica del modello di strategia che può sempre essere usata se gli oggetti strategia sono semplici come una funzione (vedi qui , ad esempio).

Tuttavia, l'essenza del tuo codice è che hai un oggetto di tipo EndResult che incapsula il modo in cui un insieme di operazioni interagisce (se le operazioni sono date da oggetti strategici o "delegati della strategia" non importa). Questo è chiamato Schema mediatore , il Mediator qui fornisce ciò che viene chiamato "contesto" in questa descrizione del modello di strategia .

Decidere tra le diverse strategie sarà tipicamente il compito di un metodo di fabbrica . Se rendi questo metodo parte del tuo mediatore (come nel tuo esempio, nel costruttore di EndResult ), o se preferisci delegarlo a un'altra classe, è qualcosa che devi decidere da solo. Dipende dalle cose delle dimensioni e dalla struttura generali di quella classe e dell'ambiente e da quanta "separazione delle preoccupazioni" di cui hai veramente bisogno. In genere, inizierei con una "piccola soluzione" (entrambe in una classe) e un refactor non appena la classe inizia a diventare "troppo grande".

    
risposta data 01.03.2016 - 13:16
fonte

Leggi altre domande sui tag