Prendete uno
strategy pattern, un
plugin pattern, un
service locator pattern e un
dependency injection pattern e metteteli assieme, cosa ottenete? Un bel risultato, direi ottimo. Battute a parte, andiamo per ordine.
Userò un esempio per definire uno
strategy pattern: supponete di sviluppare del codice per una applicazione, che calcola buste paga per alcune categorie di lavoratori, associando diversi algoritmi di logica per ciascun tipo di lavoratore. Probabilmente scrivereste qualcosa del tipo:
<span style="font-size:1.0em">
public abstract class Impiegati
{ public virtual void CalcolaStipendio()
{
}
}
public class Impiegato : Impiegati
{ public override void CalcolaStipendio()
{ ...
}
}
public class Manager : Impiegati
{ public override void CalcolaStipendio()
{ ...
}
}
public class Quadro : Impiegati
{ public override void CalcolaStipendio()
{ ...
}
}
</span>
per ogni categoria di lavoratori dovrete mantenere - e soprattutto manutenere - l'implementazione del calcolo dello stipendio; ovviamente in un caso reale le categorie di lavoratori (ma soprattutto i contratti collettivi) sono molti di più e tendono a cambiare nel tempo, quindi la manutenzione del codice è d'obbligo. Applicando lo
strategy pattern il codice diventerebbe più o meno così:
<span style="font-size:1.0em">
public interface ICalcolaStipendio
{ void CalcolaStipendio();
}
public class CalcolaImpiegato : ICalcolaStipendio
{ public void CalcolaStipendio()
{ ...
}
}
public class CalcolaManager: ICalcolaStipendio
{ public void CalcolaStipendio()
{ ...
}
}
ublic class CalcolaQuadro: ICalcolaStipendio
{ public void CalcolaStipendio()
{ ...
}
}
public abstract class Impiegati
{ private ICalcolaStipendio calcolaStipendio;
public void SetCalcolo(ICalcolaStipendio calcolo)
{ calcolaStipendio = calcolo;
}
public virtual void CalcolaStipendio()
{ calcolaStipendio.CalcolaStipendio();
}
}
public class Impiegato : Impiegati
{ public Impiegato()
{ SetCalcolo(new CalcolaImpiegato());
}
}
public class Manager : Impiegati
{ public Manager()
{ SetCalcolo(new CalcolaManager());
}
}
public class Quadro : Impiegati
{ public Quadro()
{ SetCalcolo(new CalcolaQuadro());
}
}
class Program
{ static void Main(string[] args)
{ Manager manager = new Manager();
Quadro quadro = new Quadro();
manager.CalcolaStipendo();
quadro.CalcolaStipendo();
Console.Read();
}
}
</span>
Non vi pare piuttosto "maneggevole" rispetto alla versione precedente? Quindi, lo
strategy pattern si adotta dichiarando una abstract class con, al suo interno, un metodo che contiene l'algoritmo; quest'ultimo viene implementato ereditandolo dalle classi concrete.