Patrón Interpreter con JavaScript

Hace unos días publicaba un ejemplo bastante simple de cómo implementar el patrón cadena de responsabilidad con JavaScript. Un amigo me largó la idea de ir por el patrón Interpreter. Así que aquí vamos.

El patrón Interpreter es útil para, como lo dice su nombre, interpretar cosas. Muy útil para la creación de analizadores sintácticos; El principio de la creación de las reglas de un lenguaje de programación por ejemplo, o para transformar un texto en otra cosa, como números romanos a decimales.

En nuestro caso supongamos lo siguiente:

get http://jsonplaceholder.typicode.com/posts/1 => data

En vez de tener que escribir el código para esta acción, queremos que el interpretador lea la cadena de texto y realice una acción particular. En este caso, realizar una petición HTTP mediante GET a una URL y luego almacenarla en una variable de nombre DATA.

Podemos separar, entonces, nuestro texto en ACCION [parámetros] LUEGO [variable].

Lo primero que necesitaremos será un objeto (Clase) que nos permita crear las diferentes parte de nuestro idioma, teniendo como parte de nuestro idioma aquello que pusimos en mayúsculas (GET y =>).

var expressionBase = Class.extend(function () {
    this.interpret = function (context) { };
});

(Volvemos a usar, como en el caso del patrón anterior, ExtendJS y además jQuery)

Luego crearemos cada una de las secciones de nuestro idioma derivadas de esta clase.

var getExpression = expressionBase.extend(function () {
 this.interpret = function (context) {
 if (context._expression.substring(0, 4) !== "get ") { throw "Incorrect syntax"; }
 
 var target = context._expression.substring(4, context._expression.indexOf(' ', 4));
 
 $.ajax({
 url: target,
 async: false,
 success: function (data) {
 context._data = data;
 }
 });
 };
});

var thenExpression = expressionBase.extend(function () {
 this.interpret = function (context) {
 var validator = context._expression.split(' => ');
 if (validator.length !== 2) { throw "Incorrect syntax near =>"; }
 };
});

var creatorExpression = expressionBase.extend(function () {
 this.interpret = function (context) {
 var holder = context._expression.substring(context._expression.indexOf('=> ') + 3).trim();
 window[holder] = context._data;
 };
});

Por supuesto, hay muchas formas de tomar los valores del texto y actuar en consecuencia. Lo importante es que hemos separado cada una de las partes funcionales de nuestro lenguaje en diferentes clases y cada una de ellas tiene una responsabilidad.

Lo siguiente será crear una pseudo factory (Otro patrón) que nos ayude a crear las reglas de nuestro lenguaje. Aquí hay que aclarar que lo mejor sería tener un árbol con toda la estructura y no una lista, pero para el ejemplo vale.

var context = function () {
 
 this._data = null;
 this._expression = null;
 var expressionTree = [];
 
 expressionTree.push(new getExpression());
 expressionTree.push(new thenExpression());
 expressionTree.push(new creatorExpression());
 
 this.expressionResult = function () {
 return this._data;
 };
 
 this.setContext = function (expression) {
 this._expression = expression;
 
 for (var i = 0; i < expressionTree.length; i++) {
 expressionTree[i].interpret(this);
 }
 };
};

Como podemos ver, la variable expressionTree (Que es un array) define el orden del lenguaje. Primero el GET, luego => y finalmente la variable destino. Con una mejor estructura podríamos crear todas las combinaciones de nuestro propio lenguaje.

Por último, ejecutamos el interpretador:

 var myContext = new context();
 myContext.setContext('get http://jsonplaceholder.typicode.com/posts/1 => data');
 
 console.log(data);

Gracias al dinamismo de JavaScript la variable data es creada conteniendo el valor resultante de la llamada.



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