1. Che cos'è il Modello Proxy
Il modello proxy è un modello di design strutturale che funge da proxy per controllare l'accesso a un particolare oggetto. In base all'oggetto di destinazione (l'oggetto che viene proxy), il modello proxy fornisce un oggetto proxy tramite il quale i client possono accedere all'oggetto di destinazione, consentendo l'aggiunta di funzionalità aggiuntive all'oggetto di destinazione.
1.1 Definizione del Modello Proxy
Il modello proxy è un modello di design che coinvolge la collaborazione di due o più oggetti. Un oggetto è l'effettivo oggetto di destinazione chiamato, mentre uno o più altri oggetti agiscono come oggetti proxy. Gli oggetti proxy intercettano l'accesso all'oggetto di destinazione, fornendo un modo indiretto per accedere all'oggetto di destinazione.
1.2 Scopo e Obiettivi del Modello Proxy
Il principale scopo del modello proxy è fornire un modo indiretto per accedere all'oggetto di destinazione, consentendo l'aggiunta di funzionalità aggiuntive all'oggetto di destinazione. Gli oggetti proxy possono gestire logiche comuni, come il controllo dell'accesso all'oggetto di destinazione, la memorizzazione nella cache e la registrazione. Il modello proxy può anche implementare il caricamento ritardato, istanziando l'oggetto di destinazione solo quando necessario.
2. Caratteristiche e Vantaggi del Modello Proxy
Il modello proxy ha le seguenti caratteristiche e vantaggi:
- Può estendere la funzionalità dell'oggetto di destinazione senza modificarlo.
- Può controllare l'accesso all'oggetto di destinazione attraverso l'oggetto proxy.
- Può eseguire operazioni aggiuntive prima o dopo l'accesso all'oggetto di destinazione.
- Può implementare il caricamento ritardato, istanziando l'oggetto di destinazione solo quando necessario.
3. Esempi di Applicazioni Pratiche del Modello Proxy
Il modello proxy è ampiamente utilizzato in molti scenari applicativi. Ecco alcuni esempi comuni di applicazioni pratiche:
- Proxy Remoto: Utilizzato per accedere agli oggetti in rete in modo locale.
- Proxy Virtuale: Utilizzato per creare oggetti costosi solo quando necessario.
- Proxy di Sicurezza: Utilizzato per controllare l'accesso agli oggetti.
- Riferimento Intelligente: Utilizzato per eseguire operazioni aggiuntive durante l'accesso agli oggetti, come il conteggio degli oggetti.
4.1 Diagramma delle Classi UML
Di seguito è riportato il diagramma delle classi UML del Modello Proxy in Golang:
4.2 Introduzione all'Esempio
Supponiamo di avere un'interfaccia Subject
che definisce un metodo Request
. Abbiamo una classe di implementazione concreta RealSubject
, che implementa l'interfaccia Subject
. Quindi creiamo una classe proxy Proxy
, che contiene un oggetto RealSubject
e implementa anche l'interfaccia Subject
. Nel metodo Request
della classe Proxy
, possiamo eseguire operazioni aggiuntive prima o dopo la chiamata al metodo Request
di RealSubject
.
4.3 Passaggio 1: Definizione dell'Interfaccia Proxy
In primo luogo, dobbiamo definire un'interfaccia Subject
che contenga un metodo Request
:
package main
type Subject interface {
Request()
}
4.4 Passaggio 2: Implementazione dell'Oggetto di Destinazione
Successivamente, implementiamo l'oggetto di destinazione specifico RealSubject
, che implementa l'interfaccia Subject
:
package main
import "fmt"
type RealSubject struct {}
func (r *RealSubject) Request() {
fmt.Println("RealSubject: Gestione della Richiesta")
}
4.5 Passaggio 3: Implementazione dell'Oggetto Proxy
Successivamente, creiamo un oggetto proxy, Proxy, che contiene un oggetto RealSubject e implementa l'interfaccia Subject. Nel metodo Request del Proxy, possiamo eseguire alcune operazioni aggiuntive prima o dopo la chiamata al metodo Request di RealSubject:
package main
import "fmt"
type Proxy struct {
realSubject *RealSubject
}
func (p *Proxy) Request() {
fmt.Println("Proxy: Pre-Request")
if p.realSubject == nil {
p.realSubject = &RealSubject{}
}
p.realSubject.Request()
fmt.Println("Proxy: Post-Request")
}
4.6 Passaggio 4: Invocazione dell'Oggetto Proxy
Infine, possiamo utilizzare l'oggetto proxy, Proxy, per invocare i metodi dell'oggetto presidiato, RealSubject:
package main
func main() {
proxy := Proxy{}
proxy.Request()
}
L'esecuzione del codice sopra produrrà l'output:
Proxy: Pre-Request
RealSubject: Gestione della Richiesta
Proxy: Post-Request
5.1 Differenze e Connessione tra il Pattern Proxy e il Pattern Decorator
Sia il pattern proxy che il pattern decorator sono pattern di progettazione strutturali, entrambi dei quali contengono un oggetto target e un oggetto proxy/decorator. Tuttavia, ci sono alcune differenze tra i due:
- Il pattern proxy coinvolge generalmente il controllo di accesso all'oggetto target, mentre il pattern decorator si concentra più sull'estensione dell'oggetto target.
- Il pattern proxy esegue tipicamente operazioni aggiuntive prima o dopo l'oggetto target, mentre il pattern decorator aggiunge dinamicamente funzionalità extra sopra l'oggetto target.
5.2 Confronto tra Proxy Statico e Proxy Dinamico
Il pattern proxy può essere suddiviso in proxy statico e proxy dinamico. Il proxy statico determina il tipo dell'oggetto proxy a tempo di compilazione, e l'oggetto proxy è scritto manualmente dal programmatore. Il proxy dinamico, d'altro canto, genera dinamicamente l'oggetto proxy a tempo di esecuzione sulla base dell'interfaccia dell'oggetto target. Il proxy dinamico è più flessibile ma anche più complesso rispetto al suo controparte statico.
5.3 Applicazione del Pattern Proxy nelle Microservices
Il pattern proxy può essere applicato in un'architettura a microservizi. Ad esempio, possiamo utilizzare un proxy per incapsulare l'accesso ad altri microservizi ed implementare meccanismi come bilanciamento del carico, limitazione del tasso e chiusura dei circuiti a livello del proxy. Questo può migliorare l'affidabilità e le prestazioni del sistema. Il pattern proxy può anche essere utilizzato per implementare la funzionalità di scoperta dei servizi e di routing.