Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
Guida al Visual Basic .NET - Metodi Factory

Guida al Visual Basic .NET

Capitolo 25° - Metodi Factory

<< Precedente Prossimo >>
Si definisce Factory un metodo che ha come unico scopo quello di creare una nuova istanza di una classe e restituire tale istanza al chiamante (dato che si parla di "restituire", i metodi Factory saranno sempre funzioni). Ora, ci si potrebbe chiedere perchè usare metodi factory al posto di normali costruttori. La differenza tra questi non è da sottovalutare: i costruttori servono ad istanziare un oggetto, ma, una volta avviati, non possono "fermarsi". Con questo voglio dire che, qualora venissero riscontrati degli errori nei parametri di creazione dell'istanza (nel caso ce ne siano), il costruttore creerebbe comunque un nuovo oggetto, ma molto probabilmente quest'ultimo conterrebbe dati erronei. Un metodo Factory, invece, controlla che tutto sia a posto prima di creare il nuovo oggetto: in questo modo, se c'è qualcosa che non va, lo può comunicare al programmatore (o all'utente), ad esempio lanciando un'eccezione o visualizzando un messaggio di errore. E' convenzione - ma è anche logica - che un metodo Factory sia definito sempre all'interno della stessa classe che corrisponde al suo tipo di output e che sia Shared (altrimenti non si potrebbe richiamare prima della creazione dell'oggetto, ovviamente). Un esempio di quanto detto:
Module Module1
    Class Document
        'Campo statico che contiene tutti i documenti
        'aperi fin'ora
        Private Shared Documents As New Hashtable
        'Identificatore del documento: un paragrafo nel prossimo
        'capitolo spiegherà in dettaglio i significato e
        'l'utilità delle variabili ReadOnly
        Private ReadOnly _ID As Int16
        'Nome del file e testo contenuto in esso
        Private ReadOnly _FileName, _Text As String

        Public ReadOnly Property ID() As Int16
            Get
                Return _ID
            End Get
        End Property

        Public ReadOnly Property FileName() As String
            Get
                Return _FileName
            End Get
        End Property

        Public ReadOnly Property Text() As String
            Get
                Return _Text
            End Get
        End Property

        'Da notare il costruttore Private: nessun client al di
        'fuori della classe può inizializzare il nuovo
        'oggetto. Solo il metodo factory lo può fare
        Private Sub New(ByVal ID As Int16, ByVal Path As String)
            Me._ID = ID
            Me._FileName = Path
            Me._Text = IO.File.ReadAllText(Path)
            'Me fa riferimento alla classe stessa
            Documents.Add(ID, Me)
        End Sub

        'Il metodo factory crea un documento se non esiste l'ID
        'e se il percorso su disco è diverso, altrimenti
        'restituisce il documento che esiste già
        Public Shared Function Create(ByVal ID As Int16, _ 
            ByVal Path As String) As Document
            If Documents.ContainsKey(ID) Then
                'Ottiene il documento già esistente con questo ID
                Dim D As Document = Documents(ID)
                'Se coincidono sia l'ID che il nome del file,
                'allora restituisce l'oggetto già esistente
                If D.FileName = Path Then
                    Return D
                Else
                    'Altrimenti restituisce Nothing, dato che non
                    'possono esistere due documenti con uguale ID,
                    'o si farebbe confusione
                    Return Nothing
                End If
            End If
            'Se non esiste un documento con questo ID, lo crea
            Return New Document(ID, Path)
        End Function
    End Class

    Sub Main()
        Dim D As Document = Document.Create(0, "C:	esto.txt")
        Dim E As Document = Document.Create(0, "C:	esto.txt")
        Dim F As Document = Document.Create(0, "C:file.txt")
        Dim G As Document = Document.Create(1, "C:file.txt")

        'Dimostra che se ID e Path coincidono, i due oggetti
        'sono la stessa istanza
        Console.WriteLine(E Is D)
        'Dimostra che se l'ID esiste già, ma il Path differisce,
        'l'oggetto restituito è Nothing
        Console.WriteLine(F Is Nothing)
        Console.ReadKey()
    End Sub
End Module 
Il codice sopra riportato crea volutamente tutte le situazioni contemplate all'interno del metodo factory statico: E ha gli stessi parametri di D, quindi nel metodo factory usato per creare E viene restituita l'istanza D già esistente; F ha lo stesso ID, quindi è Nothing. A prova di ciò, sullo schermo apparirà il seguente output:
True
True 


Classi factory e oggetti immutabili

Una classe contenente solo metodi factory è detta classe factory. Il più delle volte, l'uso di una tattica simile a quella sopra riportata potrebbe portare alcuni dubbi: dato che esistono due variabili che puntano alla stessa istanza, il modificarne l'una potrebbe causare l'automatica modifica dell'altra. Tuttavia, spesse volte, gli oggetti che possono essere creati con metodi factory non espongono alcun altro metodo per la modifica o l'eliminazione dello stesso oggetto, che quindi non può essere cambiato in alcun modo. Oggetti di questo tipo sono detti immutabili: un esempio di oggetti immutabili sono la stringhe. Al contrario di come si potrebe pensare, una volta create il loro valore non può essere cambiato: l'unica cosa che si può fare è assegnare alla variabile stringa un nuovo valore:
'Questa stringa è immutabile
Dim S As String = "Ciao"
'Viene creata una nuova stringa temporanea con valore "Buongiorno"
'e assegnata a S. "Ciao" verrà distrutta dal Garbage Colletcion
S = "Buongiorno" 
<< Precedente Prossimo >>
A proposito dell'autore

Programmatore e analista .NET 2005/2008/2010 (in particolare C# e VB.NET), anche nell'implementazione Mono per Linux. Conoscenze approfondite di Pascal, PHP, XML, HTML 4.01/5, CSS 2.1/3, Javascript (e jQuery). Conoscenze buone di C, LUA, GML, Ruby, XNA, AJAX e Assembly 68000. Competenze basilari di C++, SQL, Hlsl, Java.