Una delle novità architetturali più innovative ed interessanti della versione 2.0 del .NET Framework è senz'altro il modello basato su Provider. Esplorando con un reflector i vari namespace del Framework, ci si imbatte spesso in tipi che includono nel loro nome la parola "Provider", a testimonianza del fatto che questa soluzione architetturale è stata usata in molti contesti. Di fatto "Provider" è diventata una di quelle buzz-word oggi di moda tra gli sviluppatori come è stato in un passato più o meno recente per i termini "AJAX" o "SOA". Ma di cosa si tratta esattamente? A cosa servono i Provider? Quali sono i vantaggi che derivano dal loro impiego?
Questo articolo introduce e spiega le motivazioni e i concetti che stanno dietro al Provider Model, con particolare riferimento ai Provider disponibili per chi sviluppa applicazioni web con ASP.NET 2.0. Nel prossimo articolo verrà fornita una spiegazione di massima dei Provider di ASP.NET 2.0, lasciando al lettore la possibilità di approfondire i vari dettagli implementativi e di utilizzo come meglio crede. Alcuni dei concetti esposti in questa introduzione vengono ripresi in articoli già pubblicati in ASPItalia.com o in fase di stesura, ai quali si rimanda per ulteriori approfondimenti e delucidazioni.
Motivazioni del Provider Model
L'idea dei Provider nasce dalla necessità di disporre di una struttura ad oggetti flessibile e facilmente estendibile, orientata a fornire nell'ambito di una applicazione le funzionalità per una particolare API. In questo concetto trova giustificazione anche il nome che è stato attribuito al modello e al relativo pattern.
Il Provider Model permette di disegnare in modo flessibile e semplice le API delle applicazioni, limitando l'accoppiamento tra i tipi e rendendo intercambiabili tra loro le diverse strategie di implementazione relative ad una determinata problematica di sviluppo. In ASP.NET 2.0 è stato fatto largo uso dei Provider, proponendo una serie di strategie di implementazione predefinite. Il modello è peraltro facilmente estendibile, in quanto ciascun sviluppatore può implementare nuovi Provider personalizzati e ridefinire il comportamento per una particolare API, specificando nell'ambito del file di configurazione il tipo concreto da caricare a runtime tramite un'operazione di Dependency Injection. Questo aspetto, che permette di definire diverse implementazioni pluggabili, rappresenta senz'altro la caratteristica più interessante e innovativa del modello.
Il pattern Strategy
Il pattern Provider rappresenta una variante dello Strategy, un noto design pattern appartenente alla famiglia dei pattern GoF (Gang of Four) di tipo comportamentale. Il pattern Strategy consente di definire una famiglia di algoritmi, incapsularli e renderli intercambiabili tra loro in modo indipendente rispetto al contesto in cui vengono richiamati.
Gli oggetti che partecipano nell'ambito dello Strategy sono:
- Strategy: è un tipo astratto che dichiara una interfaccia comune a tutti gli algoritmi supportati. Context utilizza questa interfaccia per richiamare un algoritmo definito da un ConcreteStrategy;
- ConcreteStrategy: implementa un particolare algoritmo usando l'interfaccia definita da Strategy;
- Context: è configurato con un oggetto ConcreteStrategy, contiene un riferimento ad un oggetto Strategy e può definire una interfaccia che permetta a Strategy di accedere alla sua struttura dati.
L'esempio di codice che segue dimostra come tramite l'applicazione del pattern Strategy sia possibile incapsulare determinate funzionalità sotto forma di oggetto, permettendo ad un ipotetico client di poter cambiare dinamicamente l'algoritmo utilizzato.
public abstract class Strategy { void AlgorithmInterface(); } public class ConcreteStrategyA : Strategy { public override void AlgorithmInterface() { // Stub... } } public class ConcreteStrategyB : Strategy { public override void AlgorithmInterface() { // Stub... } } public class ConcreteStrategyC : Strategy { public override void AlgorithmInterface() { // Stub... } } public class Context { private Strategy _strategy; public Context(Strategy currentStrategy) { _strategy = currentStrategy; } public void ContextInterface() { _strategy.AlgorithmInterface(); } } class ClientApp { [STAThread] static void Main() { Context context; context = new Context(new ConcreteStrategyA()); context.ContextInterface(); context = new Context(new ConcreteStrategyB()); context.ContextInterface(); context = new Context(new ConcreteStrategyC()); context.ContextInterface(); } }
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.