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.