-----------------------------------

Acquista i software ArcGIS tramite Studio A&T srl, rivenditore autorizzato dei prodotti Esri.

I migliori software GIS, il miglior supporto tecnico!

I migliori software GIS, il miglior supporto tecnico!
Azienda operante nel settore GIS dal 2001, specializzata nell’utilizzo della tecnologia ArcGIS e aderente ai programmi Esri Italia Business Network ed Esri Partner Network

-----------------------------------



domenica 22 marzo 2009

NVI (Non-Virtual Interface) pattern

Quando si progetta una classe base specificatamente per essere utilizzata da classi che possono ereditare, si dichiarano ad esempio i metodi virtuali di modo che le classi derivate possano modificarne il comportamento.
In questo esempio eseguendo il metodo main nella console avremo come output: "Derived method".




public class EntryPoint
{
static void Main(string[] args)
{
Base b = new Derived();
b.Method();
}
}
public class Base
{
public virtual void Method()
{
Console.WriteLine("Base method");
}
}
public class Derived : Base
{
public override void Method()
{
Console.WriteLine("Derived method");
}
}
Supponiamo ora che abbiamo distribuito la nostra classe base a molte persone che hanno a loro volta utilizzato questa classe per crearsi le loro classi derivate ( la nostra classe base non è marcata sealed ed ha metodi virtuali) e che vogliamo modificare la nostra classe base aggiungendo ad esempio un tracker dei metodi per il nostro log di debug (ad esempio utilizzando log4Net). In questa forma, se dovessimo agire sul codice aggiungendo un pre e post metodo di log, dovremmo chiedere a tutti coloro che hanno utilizzato la classe base di modificare il loro codice in base alla nostra aggiunta.





public class Base
{
private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public virtual void Method()
{
_log.Debug("Start method");
Console.WriteLine("Base method");
_log.Debug("End method");
}
}
Per evitare questo problema possiamo modificare la classe base utilizzando il pattern NVI:




public class Base
{
public void Method()
{
CoreMethod();
}
protected virtual void CoreMethod()
{
Console.WriteLine("Base method");
}
}
public class Derived : Base
{
protected override void CoreMethod()
{
Console.WriteLine("Derived method");
}
}



In questo modo, noi possiamo cambiare la classe base senza che gli utenti che hanno creato le classi derivate debbano modificare il loro codice:


public class Base
{
private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public void Method()
{
_log.Debug("Start method");
CoreMethod();
_log.Debug("End method");
}
protected virtual void CoreMethod()
{
Console.WriteLine("Base method");
}
}
In sostanza, abbiamo modificato a non virtuale l'interfaccia pubblica (Method) ed abbiamo spostato il metodo overrideable in un altro metodo protetto (CoreMethod()).

Nessun commento: