Design Pattern - Aggiunta di funzioni a una classe

1

Mi sto trovando in grado di risolvere un problema di progettazione.

Per semplicità, userò C # (Web API).

Diciamo che ho una classe astratta RestController :

public abstract class RestController
{
    // ... Irrelevant code here

    protected virtual async Task<IHttpActionResult> UseAuthorization(HttpMethod method, Func<Task<IHttpActionResult>> operation)
    {
         return await operation();
    }

    protected virtual async Task<IHttpActionResult> UseHttpCache(Func<Task<IHttpActionResult>> operation)
    {
         return await operation();
    }

    // ... Irrelevant code here
}

Questi due metodi sarebbero stati sovrascritti e reimplementati da classi figlio. Qualsiasi classe che vorrebbe solo estendere da RestController e non vuole utilizzare le funzionalità di autorizzazione o cache, potrebbe semplicemente voler lasciare intatti questi metodi, poiché l'implementazione di base predefinita non fa nulla.

Ora, stavo pensando di avere qualcosa del genere:

public abstract class CachedRestController : RestController
{
      protected override async Task<IHttpActionResult> UseHttpCache(Func<Task<IHttpActionResult>> operation)
      {
            IHttpActionResult result = await operation();
            return new HttpCachedResult(result);
      }
}

public abstract class AuthenticatedRestController : RestController
{
      protected override async Task<IHttpActionResult> UseAuthorization(HttpMethod method, Func<Task<IHttpActionResult>> operation)
      {
            return IsAuthenticated(method) ?
                   await operation() :
                   Unauthorized();
      }
}

Il mio obiettivo è raggiungere qualcosa di simile al seguente:

public class MyController : CachedRestController, AuthenticatedRestController
{

}

Aggiungere o rimuovere funzionalità (memorizzazione nella cache, autenticazione, ecc.), sarebbe facile come aggiungere o rimuovere le classi genitore.

Purtroppo, come tutti sappiamo, l'ereditarietà multipla non è supportata in C #, quindi non posso andare con quella soluzione.

Sto cercando un buon modello di progettazione (compatibile con C #) che otterrebbe più o meno ciò che sto cercando.

Conosco il Design pattern di Decorator , ma avere un controller come un campo mi fa quasi paura, dato che sono responsabile della sua creazione (il framework Web Api dovrebbe esserne responsabile).

    
posta Matias Cicero 26.06.2015 - 15:26
fonte

1 risposta

7

Questo sembra uno di quei comuni scenari di "composizione di favore rispetto all'ereditarietà". Un RestController funge da endpoint per le chiamate REST. Non qualcosa per governare l'Autorizzazione. Non è qualcosa per controllare la HttpCache. È una violazione del principio di responsabilità unica.

Invece, dovresti avere classi (strategie se preferisci) per governare queste due responsabilità. Quindi puoi comporli come necessario in altri controller.

    
risposta data 26.06.2015 - 15:42
fonte

Leggi altre domande sui tag