Patrón State con JavaScript

Siguiendo con esta idea de los patrones de diseño con JavaScript, y a pedido de (Otra vez) algunos amigos, vamos con el patrón State.

Este patrón es bastante simple pero puede ser implementado de diferentes formas, dependiendo del lenguaje de programación que usemos. En JavaScript, desde lo personal, me gusta jugar un poco con las funciones y algunas referencias a las mismas.

Este patrón, en resumen, permite modificar el comportamiento de un objeto en base a cosas que pudiesen pasar dentro del mismo. De cara al consumidor del objeto, esto se aprecia solo por medio de los resultados del objeto. Otro motivo por el cual utilizar este patrón es el de ahorrarnos en complicados switchs e ifs para realizar determinadas acciones.

Supongamos lo siguiente:

contador += 1
if (contador < 10)
  EjecutarX()
else
  EjecutarY()

En el caso anterior, el código se repetiría indefinidamente, sumando la variable contador y evaluando el if constantemente. Internamente, una función o la otra se ejecutarían en base al estado interno de la variable. El problema de esto es que (Y si bien así como lo vemos no es un problema realmente) si tenemos muchos estados (ifs o switchs) puede ser difícil de mantener y depurar por lo que el patrón en cuestión sería una mejor aproximación.

var State = (function () {

   var state = function () {
      ...
       this._counter = 1;
    };
 
    state.prototype.run = function () {
       var self = this;
      ...
    };
 
    return state;
}());

Lo primero es crear un objeto. En este dejamos la variable _counter y una función run. Además agregaremos dos funciones que representarán el estado del objeto en diferentes momentos de la ejecución.

 state.prototype.state1 = function () {
   console.log("Estado 1");
    this._counter++;
    if (this._counter > 10) {
       this._innerPointer = this.state2;
    }
 };
 
 state.prototype.state2 = function () {
    console.log("Estado 2");
 };

También una función vacía, que si notamos en la función state1 notaremos que se utiliza para asignar la función state2 cuando el contador es superior a 10.

 state.prototype._innerPointer = function () {
 };

El último cambio será en la función run donde iniciaremos un intervalo de 1 segundo ininterrumpido y que llamará a la función _innerPointer. Esta función fue asignada con el estado 1 al inicio del objeto. De esta forma, cada vez que se llame a _innerPointer en realidad se estará llamando a state1. Luego de ser llamada 10 veces, state1 cambiará la referencia de _innerPointer a state2 y esta función se ejecutará indefinidamente.

var State = (function () {

   var state = function () {
       this._innerPointer = this.state1;
       this._counter = 1;
    };
 
    state.prototype.run = function () {
       var self = this;
       setInterval(function () {
          self._innerPointer.call(self);
       }, 1000);
    };
 
    state.prototype._innerPointer = function () {
    };
 
    state.prototype.state1 = function () {
       console.log("Estado 1");
       this._counter++;
       if (this._counter > 10) {
          this._innerPointer = this.state2;
       }
    };
 
    state.prototype.state2 = function () {
       console.log("Estado 2");
    };
 
    return state;
}());

 



Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s