Buscar..
Patrón observador
El patrón Observer se utiliza para el manejo y delegación de eventos. Un sujeto mantiene una colección de observadores. El sujeto luego notifica a estos observadores cuando ocurre un evento. Si alguna vez ha usado addEventListener
entonces ha utilizado el patrón Observer.
function Subject() {
this.observers = []; // Observers listening to the subject
this.registerObserver = function(observer) {
// Add an observer if it isn't already being tracked
if (this.observers.indexOf(observer) === -1) {
this.observers.push(observer);
}
};
this.unregisterObserver = function(observer) {
// Removes a previously registered observer
var index = this.observers.indexOf(observer);
if (index > -1) {
this.observers.splice(index, 1);
}
};
this.notifyObservers = function(message) {
// Send a message to all observers
this.observers.forEach(function(observer) {
observer.notify(message);
});
};
}
function Observer() {
this.notify = function(message) {
// Every observer must implement this function
};
}
Ejemplo de uso:
function Employee(name) {
this.name = name;
// Implement `notify` so the subject can pass us messages
this.notify = function(meetingTime) {
console.log(this.name + ': There is a meeting at ' + meetingTime);
};
}
var bob = new Employee('Bob');
var jane = new Employee('Jane');
var meetingAlerts = new Subject();
meetingAlerts.registerObserver(bob);
meetingAlerts.registerObserver(jane);
meetingAlerts.notifyObservers('4pm');
// Output:
// Bob: There is a meeting at 4pm
// Jane: There is a meeting at 4pm
Patrón mediador
Piense en el patrón de mediador como la torre de control de vuelo que controla los aviones en el aire: dirige este avión para aterrizar ahora, el segundo para esperar y el tercero para despegar, etc. Sin embargo, nunca se permite que un avión hable con sus compañeros .
Así es como funciona el mediador, funciona como un centro de comunicación entre diferentes módulos, de esta manera reduce la dependencia de los módulos entre sí, aumenta el acoplamiento suelto y, por consiguiente, la portabilidad.
Este ejemplo de sala de chat explica cómo funcionan los patrones de mediadores:
// each participant is just a module that wants to talk to other modules(other participants)
var Participant = function(name) {
this.name = name;
this.chatroom = null;
};
// each participant has method for talking, and also listening to other participants
Participant.prototype = {
send: function(message, to) {
this.chatroom.send(message, this, to);
},
receive: function(message, from) {
log.add(from.name + " to " + this.name + ": " + message);
}
};
// chatroom is the Mediator: it is the hub where participants send messages to, and receive messages from
var Chatroom = function() {
var participants = {};
return {
register: function(participant) {
participants[participant.name] = participant;
participant.chatroom = this;
},
send: function(message, from) {
for (key in participants) {
if (participants[key] !== from) {//you cant message yourself !
participants[key].receive(message, from);
}
}
}
};
};
// log helper
var log = (function() {
var log = "";
return {
add: function(msg) { log += msg + "\n"; },
show: function() { alert(log); log = ""; }
}
})();
function run() {
var yoko = new Participant("Yoko");
var john = new Participant("John");
var paul = new Participant("Paul");
var ringo = new Participant("Ringo");
var chatroom = new Chatroom();
chatroom.register(yoko);
chatroom.register(john);
chatroom.register(paul);
chatroom.register(ringo);
yoko.send("All you need is love.");
yoko.send("I love you John.");
paul.send("Ha, I heard that!");
log.show();
}
Mando
El patrón de comando encapsula los parámetros de un método, el estado actual del objeto y el método al que llamar. Es útil para compartimentar todo lo necesario para llamar a un método en un momento posterior. Puede usarse para emitir un "comando" y decidir más adelante qué pieza de código usar para ejecutar el comando.
Hay tres componentes en este patrón:
- Mensaje de comando: el comando en sí, incluido el nombre del método, los parámetros y el estado
- Invoker: la parte que indica al comando que ejecute sus instrucciones. Puede ser un evento temporizado, la interacción del usuario, un paso en un proceso, una devolución de llamada o cualquier forma necesaria para ejecutar el comando.
- Receptor - el objetivo de la ejecución del comando.
Mensaje de comando como una matriz
var aCommand = new Array();
aCommand.push(new Instructions().DoThis); //Method to execute
aCommand.push("String Argument"); //string argument
aCommand.push(777); //integer argument
aCommand.push(new Object {} ); //object argument
aCommand.push(new Array() ); //array argument
Constructor para clase de comando
class DoThis {
constructor( stringArg, numArg, objectArg, arrayArg ) {
this._stringArg = stringArg;
this._numArg = numArg;
this._objectArg = objectArg;
this._arrayArg = arrayArg;
}
Execute() {
var receiver = new Instructions();
receiver.DoThis(this._stringArg, this._numArg, this._objectArg, this._arrayArg );
}
}
Invocador
aCommand.Execute();
Puede invocar:
- inmediatamente
- en respuesta a un evento
- en una secuencia de ejecucion
- como una respuesta de devolución de llamada o en una promesa
- al final de un bucle de eventos
- En cualquier otra forma necesaria para invocar un método.
Receptor
class Instructions {
DoThis( stringArg, numArg, objectArg, arrayArg ) {
console.log( `${stringArg}, ${numArg}, ${objectArg}, ${arrayArg}` );
}
}
Un cliente genera un comando, lo pasa a un invocador que lo ejecuta de inmediato o lo retrasa, y luego el comando actúa sobre un receptor. El patrón de comando es muy útil cuando se usa con patrones complementarios para crear patrones de mensajería.
Iterador
Un patrón de iterador proporciona un método simple para seleccionar, de forma secuencial, el siguiente elemento de una colección.
Colección fija
class BeverageForPizza {
constructor(preferenceRank) {
this.beverageList = beverageList;
this.pointer = 0;
}
next() {
return this.beverageList[this.pointer++];
}
var withPepperoni = new BeverageForPizza(["Cola", "Water", "Beer"]);
withPepperoni.next(); //Cola
withPepperoni.next(); //Water
withPepperoni.next(); //Beer
En ECMAScript 2015, los iteradores están incorporados como un método que devuelve hecho y valor. hecho es verdadero cuando el iterador está al final de la colección
function preferredBeverage(beverage){
if( beverage == "Beer" ){
return true;
} else {
return false;
}
}
var withPepperoni = new BeverageForPizza(["Cola", "Water", "Beer", "Orange Juice"]);
for( var bevToOrder of withPepperoni ){
if( preferredBeverage( bevToOrder ) {
bevToOrder.done; //false, because "Beer" isn't the final collection item
return bevToOrder; //"Beer"
}
}
Como generador
class FibonacciIterator {
constructor() {
this.previous = 1;
this.beforePrevious = 1;
}
next() {
var current = this.previous + this.beforePrevious;
this.beforePrevious = this.previous;
this.previous = current;
return current;
}
}
var fib = new FibonacciIterator();
fib.next(); //2
fib.next(); //3
fib.next(); //5
En ECMAScript 2015
function* FibonacciGenerator() { //asterisk informs javascript of generator
var previous = 1;
var beforePrevious = 1;
while(true) {
var current = previous + beforePrevious;
beforePrevious = previous;
previous = current;
yield current; //This is like return but
//keeps the current state of the function
// i.e it remembers its place between calls
}
}
var fib = FibonacciGenerator();
fib.next().value; //2
fib.next().value; //3
fib.next().value; //5
fib.next().done; //false