miércoles, 6 de febrero de 2013

Singleton Pattern


  • Clasificación del patrón: creacional.
  • Intención: garantiza que una clase tenga únicamente una instancia y proporciona un punto de acceso global a la misma.
  • También conocido como: ---
  • Aplicabilidad: Se utiliza este patrón cuando:
    • debe haber exactamente una instancia de una clase, y debe ser accesible a los clientes desde un punto de acceso conocido. 
    • la instancia única deba ser extensible por medio de subclases, y los clientes deban ser capaces de utilizar una instancia extendida sin modificar su código.
  •  Estructura:
  • Participantes
    • Singleton: es el responsable de crear y mantener una única referencia a si mismo.
    • define una operación getInstance que permite a los clientes acceder a su instancia única. Su constructor debe ser escondido de la interfaz pública (protegido o privado), para que la clase no pueda ser directamente instanciada, o sobreescrito y que llame al método getInstance.
  • Colaboraciones
    • Client-Singleton: los clientes sólo pueden instanciar la clase Singleton através de su método getInstance.
  • Consecuencias
    • Controla el acceso a su única instancia. 
    • Evita contaminar el espacio de nombres de variables globales que almacenan los casos individuales.
    • La clase Singleton puede tener subclases, y es fácil de configurar un cliente con una instancia de esta subclase.
    • Permite un número variable de instancias, utilizando el mismo enfoque.  Sólo tiene que cambiar el método getInstance.
    • Más flexible que clases estáticas, ya que el Singleton puede ser redefinido por las subclases y las clases estáticas no.
  • Implementación
    • Asegurar una única instancia.
      • Sobreescribiendo el constructor.
      • Teniendo una referencia a si mismo.
      • Creando un método que devuelva la única instanca.
    • Elegir una subclase del singleton
      • mediante la inicialización de la variable -instance, con una instancia de la subclase a utilizar.
      • agregando una variable de entorno que permita a getInstance saber, mediante estructuras condicionales, qué tipo de subclase debe instanciar.
      • tomando la implementación de getInstance() de la clase padre (ej. MazeFactory) y ponerla en la subclase.
      • registrando cada subclase Singleton bajo un nombre determinado dentro de un registro. Cuando se necesita un singleton, getInstance() consulta el registro solicitando el singleton por su nombre. El registro busca la correspondiente singleton (si existe) y lo devuelve. Este enfoque libera getInstance() de conocer todas las subclases Singleton posibles.
  • Patrones relacionados
    • Muchos patrones pueden ser implementados utilizando el patrón Singleton, entre ellos Abstract Factory, Builder y Prototype.
  • Motivación

State Pattern

  • Clasificación del patrón: de comportamiento.
  • Intención: Alterar el comportamiento de un objeto según el estado interno en que se encuentre. Así, el objeto aparentará cambiar de clase.
  • También conocido como: Objects for States.
  • Aplicabilidad: Se utiliza este patrón cuando:
    • El comportamiento de un objeto depende de su estado, y tiene que cambiar su comportamiento en tiempo de ejecución en función de ese estado.
    • Se presentan muchos condicionales en el código, es posble que sea necesario aplicar este patrón.
  • Estructura: se puede definir de dos formas
  • Participantes
    • Context: define una interface para el cliente y mantiene una instancia del estado concreto actual.
    • State: define una interfaz para el encapsulamiento asociado a un estado particular.
    • Concrete State: implementa el comportamiento de un estado del contexto.
  • Colaboraciones
    • Context delega al ConcreteState sus peticiones.
    • Context puede pasarse a si mismo como parámetro al ConcreteState.
    • Los clientes pueden configurar un Context con un ConcreteState y luego no tiene que lidiar directamente con el estado.
    • Tanto Context como ConcreteState pueden decidir qué estado sucede a otro y bajo qué circunstancias.
  • Consecuencias
    • Se localizan fácilmente las responsabilidades de los estados específicos. Esto facilita la ampliación de estados.
    • Hace los cambios de estado explícitos puesto que en otros tipos de implementación los estados se cambian modificando valores en variables
    • Evita la  utlización de estructuras condicionales.
    • Se incrementa el número de subclases.
    • Impone una estructura sobre el código y hace más clara su intención.
    • Hace explícitas las transiciones entre cuándo se tiene que ejecutar un comportamiento u otro.
    • Los objetos state pueden ser compartidos por varios contextos.
    • Permite a un objeto cambiar de clase en tiempo de ejecución
  • Implementación
    • Las transiciones puede hacerla
      •  la subclase, conociendo qué estado le precede y cuándo.
      • el contexto, tras la solicitud del cliente.
    • Table-driven state machines: define transiciones de estado en una tabla. Esto convierte el código condicional en una tabla de consulta. Así, se puede cambiar los criterios de transición mediante la modificación de datos en lugar de cambiar el código del programa.
    • Creación y destrucción de objetos de estados. Se presentan dos posibilidades:
      • Crear el objeto cuando es necesario, utilizarlo y destruirlo. Es útil cuando no se sabe qué estado tomará el objeto en tiempo de ejecución.
      • Crear todos los estados de antemano, utilizar alguno cuando sea necesario y nunca destruirlos. Es apropiado cuando se requieren rápidos cambios de estado. La desventaja es que el contexto debe mantener una referencia por cada estado.
    • Se puede reemplazar el patrón State por herencia, cambiando la clase del objeto en tiempo de ejecución, pero esto no es posible en la mayoría de los lenguajes de programación orientados a objetos, salvo raras excepciones como Self.
  • Patrones relacionados
    •  Flyweight Pattern explica cuándo y cómo los estados pueden ser compartidos.
    • State Pattern a menudo utilizan en Singleton Pattern.
  • Motivación/Ejemplos
    • Una alarma con estado encendido, apagado, en configuración, permitirá hacer cosas diferentes de acuerdo a su estado. 
    • Conexión TCP

martes, 5 de febrero de 2013

Strategy Pattern

  • Clasificación del patrón: de comportamiento.
  • Intención: Define un conjunto de clases que representan comportamientos similares: se trata de hacer lo mismo, pero de diferente manera. Permite que un algoritmo varíe independientemente de los clientes que lo utilizan, y puedan intercambiarlos en tiempo de ejecución.
  • También conocido como: Polici, patrón estrategia.
  • Aplicabilidad: Se utiliza este patrón cuando:
    • Muchas clases relacionadas difieren sólo en su comportamiento.
    • Se necesita diferentes variantes de un algoritmo.
    • Se presentan muchos condicionales en el código, es posble que sea necesario aplicar este patrón.
    • Si un algoritmo utiliza información que no deberían conocer los clientes, la utilización del patrón estrategia evita la exposición de dichas estructuras. 
  •  Estructura:


  • Participantes
    • Context: es el responsable de crear y mantener una referencia a una estrategia concreta.
    • Strategy: es quien declara la interfaz común a todos los algoritmos soportados. Mediante esta interfaz, el contexto puede llamar a un algoritmo concreto.
    • Concrete Strategy: es quien realmente implementa el argoritmo.
  • Colaboraciones
    • Context-Strategy: El contexto debe brindar a Strategy todos los datos que requiera el algoritmo. Incluso, el contexto puede pasar una referencia de si mismo, para permitirle a la estrategia hacer callback.
    • Client-Context:Los clientes del contexto lo configuran con una estrategia concreta
  • Consecuencias
    • Puede aparecer lógica bastante parecida entre las Concrete Strategies. La herencia puede ayudar a factorizar las partes comunes de las familias de algoritmos.
    • Si bien algo similar a este patrón podría hacerse con subclases que hereden del contexto, encapsular el algoritmo en clases de estrategias separadas  permite variar el algoritmo independientemente del contexto, por lo que es más fácil de cambiar, entender y extender.
    • Las estrategias eliminan las sentencias condicionales.
    • Provee diferentes implementaciones de un mismo comportamiento. 
    • Los clientes deben conocer las diferentes estrategias y debe comprender las posibilidades que ofrecen. 
    • Comunicación sobrecargada: algunas ConcreteStrategies no utilizarán todos los parámetros, e incluso puede que alguna implementación no utilice ninguno.
    • Menor eficiencia. Aumenta el número de objetos creados.
  • Implementación
    • Definir la relación context-strategy. Ya sea 
      • pasando valores por parámetro, con la posibilidad de envío de datos innecesarios.
      • pasando el contexto como parámetro, que supone un alto acoplamiento entre clases (a tal punto de parecer una única clase)
      • Mantener en la estrategia una referencia al contexto (podría ser un contexto Singleton). 
    • Se podría definir una estrategia por defecto, para ahorrarle decisiones al cliente. Esto hace que la asignación de una estrategia sea opcional.
  • Patrones relacionados
    • Template Method. Una intención similar pero haciendo uso de la herencia en lugar de delegación
    • Flyweight. Útil para aminorar los efectos del aumento de la población de objetos
  • Motivación
    • Dividir un flujo de texto en líneas.
      • El cliente no siempre querrá leer un archivo, por lo tanto tener una clase enorme podría resultar poco útil.
      • Existen diferentes algoritmos que permiten leer texto desde un archivo, y ponerlos a todos en la misma clase será muy grande y difícil de mantener.
      • Es difícil añadir nuevos algoritmos o modificar los existentes son una parte integral de una sola clase.
    • Pagar un servicio mediante diferentes medios. Problemas:
      • Existen diferentes algoritmos que permiten registrar una transacción por difeerentes medios. Por ejemplo, mediante tarjeta de crédito, mediante efectivo, mediante PagoFácil... El cliente no pagará con todos los medios de pago. Sólo elegirá uno.
      • Si todos los algoritmos estuviesen en la misma clase, la misma sería muy grande y difícil de mantener.
      • Es difícil añadir nuevos algoritmos o modificar los existentes si son parte de una sola clase.
    • Dibujar un tipo de recorrido en un mapa, de acuerdo al medio de transporte elegido.
    • Existen diversos algoritmos a implementar, seún el usuario recorra un sitio a pie, en colectivo o en auto. Sin embargo, el usuario sólo elegirá un medio.
    • Si todos los algoritmos estuviesen en la misma clase, la misma sería muy grande y difícil de mantener.
    • Es difícil añadir nuevos algoritmos o modificar los existentes si son parte de una sola clase.