posts - 315, comments - 268, trackbacks - 15

My Links

News

View Pietro Libro's profile on LinkedIn

DomusDotNet
   DomusDotNet

Pietro Libro

Tag Cloud

Article Categories

Archives

Post Categories

Blogs amici

Links

Design Pattern: Proxy Pattern

Con questo post, vorrei iniziare un nuovo “filone” del mio blog a riguardo dei Design Pattern. Penso che descrivere e contestualmente tirar giù qualche riga di codice d’esempio,  possa essere un ottimo esercizio (personale) per meglio comprendere un problema (nello specifico un pattern), o per creare un momento di riflessione/discussione sull’argomento.

Una definizione di Pattern, che a mio parere descrive bene cosa esso sia è: “Un Pattern è una descrizione di una soluzione, riusabile per un problema ben conosciuto”. L’idea è quella di descrivere la soluzione in un linguaggio comprensibile (come il linguaggio naturale) prima di tradurla in linee di codice. Per Design Pattern, possiamo affidarci a Wikipedia:

A design pattern in architecture and computer science is a formal way of documenting a solution to a design problem in a particular field of expertise. The idea was introduced by the architect Christopher Alexander in the field of architecture and has been adapted for various other disciplines, including computer science. An organized collection of design patterns that relate to a particular field is called a pattern language.

Dopo questa breve (brevissima) introduzione, penso che sia abbastanza chiaro il vantaggio di utilizzare uno o più Design Pattern (quelli necessari) durante il Design e lo sviluppo delle nostre applicazioni.

In questo primo post vediamo il “Proxy Pattern”.

Dagli autori (GoF, gang of four) del libro “Design Patterns: Elements of Reusable Object-Oriented Software”, il Proxy Pattern è descritto come l’intento di fornire un segnaposto o surrogato di  un altro oggetto di cui si vuole controllare l’accesso. Del resto, una classe proxy, nella sua forma più generale è una classe che si comporta come “interfaccia” per qualcos’altro. Di questo pattern ne esistono diverse varianti, tra cui:

- Virtual Proxy (o Lazy Instantiation Pattern)

- Protection Proxy (o Security Proxy)

 

Virtual Proxy (Lazy Instantiation Pattern)

 

Un’applicazione, normalmente, è un insieme di componenti. Questi non necessariamente devono essere tutti caricati quando l’applicazione si avvia, soprattutto nel caso in cui alcuni di questi richiedano un certo numero di risorse (come ad esempio una collezione di immagini ad alta risoluzione, un database ad oggetti, un grafo di oggetti molto denso ecc …). In questi casi si può ipotizzare di eseguire il load di questi componenti solo quando richiesti dal client (on demand). In casi come questi possiamo utilizzare il Virtual Proxy Pattern che esegue il defer (o Lazy Loading) del processo di creazione di oggetti (componenti) memory-intensive migliorando le performance dell’applicazione. A questo punto qualcuno potrebbe dire che in casi come questi all’avvio dell’applicazione utilizzo un thread secondario o un pool di thread per caricare il componente o gli oggetti che richiedono un uso intensivo delle risorse, ma se questi oggetti non verranno mai utilizzati dall’applicazione, perché “sprecare” risorse di sistema?

Un esempio di utilizzo di questo pattern potrebbe essere il seguente:

Supponiamo di avere un processo che impiega molto tempo a recuperare un’immagine ad esempio da un database remoto o tramite una richiesta web. Supponiamo anche che la visualizzazione di quest’immagine potrebbe essere richiesta solo in alcuni scenari di utilizzo della nostra applicazione. Potremmo implementare il Virtual Proxy Pattern in questo modo:

Prima di tutto, aggiungiamo un’interfaccia denominata ad esempio IRemoteResource che definisce il metodo GetResource() per ottenere un’immagine dal web.

   1: public interface IRemoteResource
   2: {
   3:     Image GetResource();
   4: }

 

Di seguito l’implementazione dell’interfaccia IRemoteResource

   1: public class RealRemoteResource : IRemoteResource
   2: {
   3:     private Image _resource = null;
   4:  
   5:     public RealRemoteResource(Guid resourceId)
   6:     {
   7:         _resource = LoadResource(resourceId);
   8:     }
   9:  
  10:     private Image LoadResource(Guid resourceId)
  11:     {
  12:         ////Download image from internet.
  13:         System.Net.WebClient wc = new System.Net.WebClient();
  14:         string address = string.Format(@"http://www.esempio.com/images/{0}.png", resourceId);
  15:         string localFilePath = string.Format(@".\Images\image_{0}.png", resourceId);
  16:         wc.DownloadFile(address, localFilePath);
  17:         return Image.FromFile(localFilePath);
  18:     }
  19:  
  20:     #region IRemoteResource Members
  21:  
  22:     public Image GetResource()
  23:     {
  24:         return _resource;
  25:     }
  26:  
  27:     #endregion
  28: }

Molto semplicemente questa classe accetta nel costruttore un argomento che specifica l’ID della risorsa (immagine) che si vuole ottenere e contestualmente chiama il metodo privato LoadResource(…) per eseguire il Download del file dall’indirizzo specificato e salvare il contenuto sul file system locale.

Di seguito l’implementazione della classe Proxy, che esegue il loading delle risorse quando richiesto:

   1: public class ProxyRemoteResource : IRemoteResource
   2: {
   3:     private Image _resource = null;
   4:     private Guid _resourceId = Guid.Empty;
   5:  
   6:     public ProxyRemoteResource(Guid resourceId)
   7:     {
   8:         _resourceId = resourceId;
   9:     }
  10:  
  11:     #region IRemoteResource Members
  12:  
  13:     public Image GetResource()
  14:     {
  15:         if (_resource == null)
  16:         {
  17:             _resource = new RealRemoteResource(_resourceId).GetResource();
  18:         }
  19:  
  20:         return _resource;
  21:     }
  22:  
  23:     #endregion
  24: }

Un esempio di utilizzo delle classi su esposte:

   1: Guid resourceId1 = Guid.Parse("559B4505-6D50-4936-8D4B-D871D00B5C1C");
   2: Guid resourceId2 = Guid.Parse("F14E2C9D-3785-4047-94C2-68361419A9E1");
   3:  
   4: ProxyRemoteResource proxyRemoteResource1 = new ProxyRemoteResource(resourceId1);
   5: ProxyRemoteResource proxyRemoteResource2 = new ProxyRemoteResource(resourceId2);
   6:  
   7: proxyRemoteResource1.GetResource(); //Load
   8: proxyRemoteResource2.GetResource(); //Load
   9: proxyRemoteResource1.GetResource(); //No loading. Already done.

Possiamo notare come alla riga 7 ed 8 siano eseguite le chiamate GetResource() per le due istanze delle classi Proxy che eseguono il Download delle immagini dal Web. Nel caso presente alla riga 9, non viene eseguito nessun download essendo stato eseguito precedentemente (riga 7).

In rete sono presenti numerosi esempi di questo pattern. Nel prossimo post approfondiremo e vedremo un esempio di Protection Proxy Pattern.

Print | posted on venerdì 25 giugno 2010 12:06 | Filed Under [ Design Pattern ]

Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET