In questo post ho deciso di parlare di tre semplici design patterns, tutti per lo più orientati all’ottimizzazione nell’esecuzione di operazioni /processi onerosi
Difficoltà:![]()
Piattaforma: VB.NET
Come prima cosa definiamo brevemente che cos’è un Design pattern.
Un Pattern è un modello o un schema, e in campo informatico, in particolare nella programmazione Object Oriented, si parla di Design pattern, per descrivere soluzioni progettuali generalizzate applicabili a determinati tipi di problemi ricorrenti o che si possono verificare in diverse situazioni.
Un design pattern è quindi caratterizzato da: un nome che generalmente ne richiama il comportamento, da una descrizione di un problema o contesto generico cui può essere applicato e da una descrizione generalizzata della soluzione che verrà applicata.
In futuro su questo blog approfondirò di più l’argomento.
Lazy Inizialization
Questo pattern è utilizzato principalmente quando è necessario effettuare operazioni di lettura dati particolarmente time consuming o impegnative. Un esempio potrebbe essere la lettura di dati di inizializzazione da un database.
Queste verranno eseguite solo quando effettivamente sono necessarie e da qui ne deriva il nome “Inizializzazione Pigra”
Come dicevo l’implementazione è estremamente semplice e prevede l’utilizzo di un flag interno usato per tracciare se i dati sono già stati effettivamente caricati.
Public Class LazyInitializerClass
Private m_DataInizialized As Boolean
Private m_DataToRead As String
Public Sub New()
m_DataInizialized = False
‘ reset Data
m_DataToRead = “”
End Sub
Public ReadOnly Property MyData() As String
Get
If Not m_DataInizialized Then Initialize()
Return m_DataToRead
End Get
End Property
Private Sub Initialize()
m_DataInizialized = True
‘ read Data
m_DataToRead = “Data From Database”
End Sub
Public Sub Refresh()
m_DataInizialized = False
End Sub
End Class
Inizialmente, quando l’oggetto viene creato, il flag viene impostato a false. Successivamente quando la property viene chiamata per la prima volta, i dati vengono letti ed il flag di controllo viene impostato a true.
Tutte le interrogazioni successive della property invece, non leggeranno più la sorgente dei dati, ma ne restituiranno direttamente il contenuto precedentemente letto.
In questo esempio ho aggiunto il metodo di refresh che ci permetta di ricaricare i dati dal DB.
Pattern IsDirty
Questo pattern è di natura simile al precedente, ed è principalmente utilizzato per ottimizzare operazioni di salvataggio di un determinato oggetto, ovvero queste ultime verranno eseguite solo quando sono state fatte effettivamente delle modifiche all’oggetto.
Anche qui il principio è molto semplice e si basa sull’utilizzo di un flag interno che viene impostato a true tutte le volte che una property cambia.
Public Class IsDirtyClass
Private m_IsDirty As Boolean
Private m_MyData As String
Public Property MyData() As String
Get
Return m_MyData
End Get
Set(ByVal value As String)
m_IsDirty = True
m_MyData = value
End Set
End Property
Public Sub New()
m_IsDirty = False
‘ reset Data
m_MyData = “”
End Sub
Public Sub Save()
If m_IsDirty Then
‘ Save Data
m_IsDirty = False
End If
End Sub
end Class
Il metodo che effettua il salvataggio verificherà quindi che almeno una property è cambiata, in caso contrario non effettuerà nessuna operazione l’inutile .
Singleton
Questo pattern si discosta leggermente dai primi due poiché, sebbene utilizzi un principio di Lazy iniziatialization, la sua caratteristica principale è quella di assicurarsi che esita una sola istanza attiva di una data classe.
E’ un pattern molto usato a volte eccessivamente o impropriamente applicato e da qui anche la fama, a mio avviso ingiustificata, di essere anche un anti pattern. Sebbene molto semplice nell’implementazione vale la pena spendere due parole in più.
Singleton è un cosi detto pattern creazionale, ovvero fa parte della famiglia di quei patterns che, modificando l’approccio standard alla creazione delle proprie istanze, (in questo caso rendendo privato il costruttore), nascondono al client le modalità in cui vengono create le istanze stesse.
I real case dove più è utilizzato sono i casi in cui è necessario centralizzare il controllo di uno o più processi su singolo oggetto, dove è necessario fornire un unico punto di accesso condiviso a determinate risorse o infine, in contesti di load balancing.
Il principio di funzionamento è molto semplice, l’istanza viene creata la prima volta che si accede alla variabile e non all’avvio del programma.
Tutte le volte che viene richiesta una nuova istanza, viene fornito il riferimento all’istanza esistente.
Per far questo viene dichiarato nella classe un oggetto interno privato dello stesso tipo della classe
Viene poi mascherato il costruttore mentre la creazione della prima istanza o la restituzione del riferimento all’istanza esistente viene fatta attraverso un metodo statico.
Public Class SingleTonClass
Private Shared m_instance As SingleTonClass
Protected Sub New()
End Sub
Public Shared Function GetInstance() As SingleTonClass
If m_instance Is Nothing Then
m_instance = New SingleTonClass
End If
Return m_instance
End Function
End Class
E’ importante ricordare che nel caso ci siano più client o thread che istanziano questa classe, è necessario, anche se il framework .NET ci viene già incontro, governarne l’accesso concorrente ai dati con dei lock.
