Visualizzazione post con etichetta Design pattern. Mostra tutti i post
Visualizzazione post con etichetta Design pattern. Mostra tutti i post
sabato 14 maggio 2011

Il pattern MVC

Il pattern MVC è un architectural pattern il cui scopo è quello di separare la rappresentazione del modello di dominio (model) dall'interfaccia utente (view) e dal controllo dell'interazione uomo-macchina (controller). Il pattern MVC è utilizzato ad esempio da Joomla e da molti altri framework come Ruby on Rails, Apache Struts etc...

Il pattern MVC

Il pattern MVC è basato sulla suddivisione dei compiti fra i componenti che interpretano i tre ruoli principali:

  1. il model fornisce i metodi per accedere ai dati utili dell'applicazione e agli algoritmi del programma.
  2. la view visualizza i dati elaborati dal model e li mostra agli utenti.
  3. il controller riceve i comandi dell'utente (in genere attraverso la view) e li attua modificando lo stato degli altri due componenti: in particolare recupera i dati dal model e li restituisce alla view stessa.

Questo schema, fra l'altro, implica anche la tradizionale separazione fra la logica applicativa (in questo contesto spesso chiamata "logica di business"), a carico del model, e l'interfaccia utente a carico della view.
lunedì 21 febbraio 2011

Factory Method Design Pattern C#

Riprendiamo oggi il nostro viaggio tra i Design Pattern: dopo aver visto l'Abstract Factory introduciamo ora il Factory Method che può essere visto come un caso più semplice. Ecco un diagramma UML di esempio:

Factory Method

Struttura di un Factory Method
  • Product: definisce l'interfaccia dell'oggetto creato dal factory method.
  • ProductOne e ProductTwo: implementano l'interfaccia di Product rappresentando i casi concreti.
  • Framework: dichiara il factory method (in questo caso makeProduct) che restituisce un oggetto di tipo Product a prescindere dal tipo concreto di prodotto; il Framework può in alcuni casi definire un'implementazione del factory method che ritorna un oggetto di default.
  • ApplicationOne: ridefinisce il factory method per restituire un'istanza di ProductOne
  • ApplicationTwo: ridefinisce il factory method per restituire un'istanza di ProductTwo

La classe Framework si affida alle sue sottoclassi per quanto riguarda la definizione del factory method, cosicché esso ritorni un'istanza appropriata del Product.
Il codice client tratta solo con l'interfaccia e con nessuna classe concreta.
sabato 16 ottobre 2010

Abstract Factory Design Pattern C#

Il pattern Abstract Factory fa parte dei cosiddetti Creational patterns cioè di quel genere di pattern che si occupa di istanziare (creare) oggetti.
La sua peculiarità è quella di fornire una interfaccia per creare famiglie di oggetti connessi o dipendenti tra loro, in modo che non ci sia necessità da parte dei client di specificare i nomi delle classi concrete all'interno del proprio codice.
Vediamo il diagramma UML:

Abstract Factory Design Pattern C#

Di seguito riportiamo la sua realizzazione in C#

// Abstract Factory pattern -- Structural example
using System;

namespace DoFactory.GangOfFour.Abstract.Structural
{
  /// <summary>
  /// MainApp startup class for Structural
  /// Abstract Factory Design Pattern.
  /// </summary>
  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    public static void Main()
    {
      // Abstract factory #1
      AbstractFactory factory1 = new ConcreteFactory1();
      Client client1 = new Client(factory1);
      client1.Run();

      // Abstract factory #2
      AbstractFactory factory2 = new ConcreteFactory2();
      Client client2 = new Client(factory2);
      client2.Run();

      // Wait for user input
      Console.ReadKey();
    }
  }

  /// <summary>
  /// The 'AbstractFactory' abstract class
  /// </summary>
  abstract class AbstractFactory
  {
    public abstract AbstractProductA CreateProductA();
    public abstract AbstractProductB CreateProductB();
  }


  /// <summary>
  /// The 'ConcreteFactory1' class
  /// </summary>
  class ConcreteFactory1 : AbstractFactory
  {
    public override AbstractProductA CreateProductA()
    {
      return new ProductA1();
    }
    public override AbstractProductB CreateProductB()
    {
      return new ProductB1();
    }
  }

  /// <summary>
  /// The 'ConcreteFactory2' class
  /// </summary>
  class ConcreteFactory2 : AbstractFactory
  {
    public override AbstractProductA CreateProductA()
    {
      return new ProductA2();
    }
    public override AbstractProductB CreateProductB()
    {
      return new ProductB2();
    }
  }

  /// <summary>
  /// The 'AbstractProductA' abstract class
  /// </summary>
  abstract class AbstractProductA
  {
  }

  /// <summary>
  /// The 'AbstractProductB' abstract class
  /// </summary>
  abstract class AbstractProductB
  {
    public abstract void Interact(AbstractProductA a);
  }


  /// <summary>
  /// The 'ProductA1' class
  /// </summary>
  class ProductA1 : AbstractProductA
  {
  }

  /// <summary>
  /// The 'ProductB1' class
  /// </summary>
  class ProductB1 : AbstractProductB
  {
    public override void Interact(AbstractProductA a)
    {
      Console.WriteLine(this.GetType().Name +
        " interacts with " + a.GetType().Name);
    }
  }

  /// <summary>
  /// The 'ProductA2' class
  /// </summary>
  class ProductA2 : AbstractProductA
  {
  }

  /// <summary>
  /// The 'ProductB2' class
  /// </summary>
  class ProductB2 : AbstractProductB
  {
    public override void Interact(AbstractProductA a)
    {
      Console.WriteLine(this.GetType().Name +
        " interacts with " + a.GetType().Name);
    }
  }

  /// <summary>
  /// The 'Client' class. Interaction environment for the products.
  /// </summary>
  class Client
  {
    private AbstractProductA _abstractProductA;
    private AbstractProductB _abstractProductB;

    // Constructor
    public Client(AbstractFactory factory)
    {
      _abstractProductB = factory.CreateProductB();
      _abstractProductA = factory.CreateProductA();
    }

    public void Run()
    {
      _abstractProductB.Interact(_abstractProductA);
    }
  }
}

L'Output prodotto da questo semplice programma sarà:

ProductB1 interacts with ProductA1
ProductB2 interacts with ProductA2
venerdì 8 ottobre 2010

Singleton Design Pattern C#

Il Singleton è uno dei pattern fondamentali della programmazione ad oggetti e viene utilizzato quando si ha l'esigenza di creare una sola istanza per una determinata classe.
In pratica se vogliamo che nella nostra applicazione ci sia un solo oggetto di un determinato tipo la "Gang of four" consiglia di utilizzare il singleton come accesso "globale" a questa unica istanza.
I requisiti per implementare questo pattern sono i seguenti:
  1. Un singolo costruttore privato e senza parametri. Questo evita che altre classi possano istanziare nuovi oggetti del tipo in questione (sarebbe una violazione del pattern) 
  2.  La presenza di una variabile statica (variabile di classe) che mantiene il riferimento all'unica istanza possibile
  3. Un metodo pubblico e statico che permette alle altre classi di accedere alla variabile del punto 2 e inizializzarla se ancora non creata.
Vediamo una semplice realizzazione in C#

public sealed class Singleton
{
    private static Singleton _instance = null;

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            if (_instance==null)
            {
                _instance = new Singleton();
            }
            return _instance;
        }
    }
}

La proprietà Instance verifica se la variabile _instance è stata già inizializzata. In caso negativo provvede alla sua inizializzazione (new Singleton()). In ogni caso viene restituito il reiferimento stesso.
In questa maniera se siamo i primi a richiedere l'oggetto Singleton (Singleton.Instance) la classe inizializza l'oggetto e ce ne restituisce il riferimento. In caso contrario ci restituirà sempre il riferimento dell'unico oggetto presente.
In realtà il codice appena mostrato non considera l'eventualità che due threads si trovino contemporaneamente a dover valutare la condizione (_instance == null). In questo caso se dovessero verificare che l'oggetto non è stato inizializzato andrebbero a creare due istanze violando palesemente il pattern. In un contesto multi-threading il codice precedente non è sicuro e deve essere modificato ad esempio in questo modo:

public sealed class Singleton
{
    private static Singleton _instance=null;
    private static readonly object _padlock = new object();

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            lock (_padlock)
            {
                if (_instance==null)
                {
                    _instance = new Singleton();
                }
                return _instance;
            }
        }
    }
}

L'introduzione di un lucchetto ci mette al riparo dalla possibilità che due thread valutino contemporaneamente la condizione di inizializzazione.