Manual de Ingeniería Informática/Patrones de Comportamiento

Chain of Responsibility (Cadena de responsabilidad) editar

Problema editar

Establecer la línea que deben llevar los mensajes para que los objetos realicen la tarea indicada.

Solución editar

Participantes:

Beneficios, Desventajas y Variantes editar

Se debe usar cuando:La Cadena de Responsabilidades ofrece una gran flexibilidad en el procesamiento de eventos para una aplicación, ya que domina el manejo de eventos complejo dividiendo las responsabilidades a través de un número de elementos simples. Permite a un grupo de clases comportarse como un todo, ya que los eventos producidos por una clase pueden ser enviados a otras clases para que los atrapen dentro del grupo. Consecuencias: Desventajas:es difícil de desarrollar, testear y debuguear. A medida que se avanza la cadena se hace mas compleja, hay que ser cuidadosos viendo si los eventos están siendo correctamente reenviados.

Ejemplo editar

Command (Orden) editar

Problema editar

Encapsula una operación en un objeto, permitiendo ejecutar dicha operación sin necesidad de conocer el contenido de la misma.

Solución editar

Beneficios, Desventajas y Variantes editar

Ejemplo editar

Interpreter (Intérprete) editar

Problema editar

Dado un lenguaje, define una gramática para dicho lenguaje, así como las herramientas necesarias para interpretarlo.

Solución editar

Beneficios, Desventajas y Variantes editar

Ejemplo editar

Iterator (Iterador) editar

Problema editar

Permite realizar recorridos sobre objetos compuestos independientemente de la implementación de estos.

Solución editar

Beneficios, Desventajas y Variantes editar

Ejemplo editar

Mediator (Mediador) editar

Problema editar

Define un objeto que coordine la comunicación entre objetos de distintas clases, pero que funcionan como un conjunto.

Solución editar

Beneficios, Desventajas y Variantes editar

Ejemplo editar

Memento (Recuerdo) editar

Problema editar

Permite volver a estados anteriores del sistema.

Solución editar

Beneficios, Desventajas y Variantes editar

Ejemplo editar

Observer (Observador) editar

Problema editar

Define una dependencia de uno-a-muchos entre objetos, de forma que cuando un objeto cambie de estado se notifique y actualicen automáticamente todos los objetos que dependen de él.

Solución editar

Beneficios, Desventajas y Variantes editar

Ejemplo editar

Ejemplo 1 (C#) editar

public class ObservableClass
{
    private Int32 _Value;

    public Int32 Value
    {
        get { return _Value; }
        set
        {
            if (_Value != value)
            {
                _Value = value;
                OnValueChanged();
            }
        }
    }

    public event EventHandler ValueChanged;

    protected void OnValueChanged()
    {
        if (ValueChanged != null)
            ValueChanged(this, EventArgs.Empty);
    }
}

public class ObserverClass
{
    public ObserverClass(ObservableClass observable)
    {
        observable.ValueChanged += TheValueChanged;
    }

    private void TheValueChanged(Object sender, EventArgs e)
    {
        Console.Out.WriteLine("Value changed to " +
            ((ObservableClass)sender).Value);
    }
}

public class Program
{
    public static void Main()
    {
        ObservableClass observable = new ObservableClass();
        ObserverClass observer = new Observer(observable);
        observervable.Value = 10;
    }
}

Ejemplo 2 implementado con Eventos (C#) editar

   
class Observable
{
    public event EventHandler SomethingHappened;

    public void DoSomething()
    {
        EventHandler handler = SomethingHappened;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

class Observer
{
    public void HandleEvent(object sender, EventArgs args)
    {
        Console.WriteLine("Something happened to " + sender);
    }
}

class Test
{
    static void Main()
    {
        Observable observable = new Observable();
        Observer observer = new Observer();
        observable.SomethingHappened += observer.HandleEvent;

        observable.DoSomething();
    }
}

Ejemplo 3 (C#) editar

namespace ObservablePattern
{
    using System;
    using System.Collections.Generic;

    internal static class Program
    {
        private static void Main()
        {
            Observable observable = new Observable();
            AnotherObservable anotherObservable = new AnotherObservable();

            using (Observer observer = new Observer(observable))
            {
                observable.DoSomething();
                observer.Add(anotherObservable);
                anotherObservable.DoSomething();
            }

            Console.ReadLine();
        }
    }

    internal interface IObservable
    {
        event EventHandler SomethingHappened;
    }

    internal class Observable : IObservable
    {
        private event EventHandler somethingHappened;

        public event EventHandler SomethingHappened
        {
            add
            {
                this.somethingHappened += value;
            }

            remove
            {
                this.somethingHappened -= value;
            }
        }

        public void DoSomething()
        {
            EventHandler handler = this.somethingHappened;

            Console.WriteLine("About to do something.");
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    }

    internal class AnotherObservable : IObservable
    {
        private event EventHandler somethingHappened;

        public event EventHandler SomethingHappened
        {
            add
            {
                this.somethingHappened += value;
            }

            remove
            {
                this.somethingHappened -= value;
            }
        }

        public void DoSomething()
        {
            EventHandler handler = this.somethingHappened;

            Console.WriteLine("About to do something different.");
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    }

    internal class Observer : IDisposable
    {
        private static readonly object listLocker = new object();
        private static readonly ReaderWriterLockSlim listItemLocker = new ReaderWriterLockSlim();
        private ICollection<IObservable> observables;
        private EventHandler eventHandler;

        public Observer()
        {
        }

        public Observer(IObservable observable)
        {
            if (observable == null)
            {
                return;
            }

            this.observables = new List<IObservable>
            {
                observable
            };

            this.eventHandler = this.HandleEvent;
            observable.SomethingHappened += this.eventHandler;
        }

        public void Add(IObservable observable)
        {
            if (observable == null)
            {
                return;
            }

            if (this.observables == null)
            {
                lock (listLocker)
                {
                    if (this.observables == null)
                    {
                        this.observables = new List<IObservable>();
                        this.eventHandler = this.HandleEvent;
                    }
                }
            }

            listItemLocker.EnterWriteLock();
            try
            {
                this.observables.Add(observable);
                observable.SomethingHappened += this.eventHandler;
            }
            finally
            {
                listItemLocker.ExitWriteLock();
            }
        }

        public void Remove(IObservable observable)
        {
             if ((observable == null) || (this.observables == null))
             {
                 return;
             }

             listItemLocker.EnterWriteLock();
             try
             {
                 this.observables.Remove(observable);
                 observable.SomethingHappened -= this.eventHandler;
             }
             finally
             {
                 listItemLocker.ExitWriteLock();
             }
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (this.observables != null)
            {
                foreach (IObservable observable in this.observables)
                {
                    observable.SomethingHappened -= this.eventHandler;
                }
            }

            GC.SuppressFinalize(this);
        }

        #endregion

        private void HandleEvent(object sender, EventArgs args)
        {
            Console.WriteLine("Something happened to " + sender);
        }
    }
}

Ejemplo 4 (C#) editar

 
class MainApp
{
    static void Main()
    {
        // Create IBM stock and attach investors
        IBM ibm = new IBM("IBM", 120.00);
        ibm.Attach(new Investor("Sorros"));
        ibm.Attach(new Investor("Berkshire"));

        // Fluctuating prices will notify investors
        ibm.Price = 120.10;
        ibm.Price = 121.00;

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

// The 'ConcreteObserver' class
class Investor : IInvestor
{
    private string _name;
    private Stock _stock;
    public Investor(string name)
    {
        this._name = name;
    }
    public void Update(Stock stock)
    {
        Console.WriteLine("Notified {0} of {1}'s " +
          "change to {2:C}", _name, stock.Symbol, stock.Price);
    }
    public Stock Stock
    {
        get { return _stock; }
        set { _stock = value; }
    }
}

// The 'ConcreteSubject' class
class IBM : Stock
{
   public IBM(string symbol, double price): base(symbol, price){}
}

// The 'Observer' interface
interface IInvestor
{
    void Update(Stock stock);
}

// The 'Subject' abstract class
abstract class Stock
{
    private string _symbol;
    private double _price;
    private List<IInvestor> _investors = new List<IInvestor>();
    // Constructor
    public Stock(string symbol, double price)
    {
        this._symbol = symbol;
        this._price = price;
    }
    public void Attach(IInvestor investor)
    {
        _investors.Add(investor);
    }
    public void Detach(IInvestor investor)
    {
        _investors.Remove(investor);
    }
    public void Notify()
    {
        foreach (IInvestor investor in _investors)
        {
            investor.Update(this);
        }
        Console.WriteLine("");
    }
    // Gets or sets the price
    public double Price
    {
        get { return _price; }
        set
        {
            if (_price != value)
            {
               _price = value;
                Notify();
            }
        }
    }
    // Gets the symbol
    public string Symbol
    {
        get { return _symbol; }
    }
}

/* Output :

Notified Sorros of IBM's change to $120.10
Notified Berkshire of IBM's change to $120.10
Notified Sorros of IBM's change to $121.00
Notified Berkshire of IBM's change to $121.00 */

State (Estado) editar

Problema editar

Permite que un objeto modifique su comportamiento cada vez que cambie su estado interno.

Solución editar

Beneficios, Desventajas y Variantes editar

Ejemplo editar

Strategy (Estrategia) editar

Problema editar

Permite disponer de varios métodos para resolver un problema y elegir cuál utilizar en tiempo de ejecución.

Solución editar

Beneficios, Desventajas y Variantes editar

Ejemplo editar

Template method (Método plantilla) editar

Problema editar

Define en una operación el esqueleto de un algoritmo, delegando en las subclases algunos de sus pasos, esto permite que las subclases redefinan ciertos pasos de un algoritmo sin cambiar su estructura.

Solución editar

Beneficios, Desventajas y Variantes editar

Ejemplo editar

Visitor (Visitante) editar

Problema editar

Permite definir nuevas operaciones sobre una jerarquía de clases sin modificar las clases sobre las que opera.

Solución editar

Beneficios, Desventajas y Variantes editar

Ejemplo editar