introducir
El modo Observador también se llama Publicar/Suscribirse. Define una relación de uno a muchos, lo que permite que múltiples objetos de observador escuchen un objeto de tema al mismo tiempo. Cuando cambia el estado de este tema, todos los objetos observadores serán notificados, para que puedan actualizarse automáticamente.
Beneficios del uso del modo Observador:
1. Admite una comunicación de transmisión simple y notifica automáticamente todos los objetos suscritos.
2. Después de cargar la página, el objeto objetivo puede tener fácilmente una correlación dinámica con el observador, lo que aumenta la flexibilidad.
3. La relación de acoplamiento abstracto entre el objeto objetivo y el observador se puede ampliar y reutilizar por separado.
Texto (versión 1)
La implementación del patrón Observador en JS se logra a través de devoluciones de llamada. Primero definamos un objeto PubSub, que contiene 3 métodos: suscripción, cancelar suscripción y publicar.
La copia del código es la siguiente:
var pubSub = {};
(función (q) {
temas var = {}, // Array almacenada por la función de devolución de llamada
subuid = -1;
// Publicar método
q.publish = function (topic, args) {
if (! temas [tema]) {
devolver falso;
}
setTimeOut (function () {
suscriptores de var = temas [tema],
len = suscriptores? suscriptores.length: 0;
mientras (len--) {
suscriptores [len] .func (tema, args);
}
}, 0);
devolver verdadero;
};
// Método de suscripción
Q.SubScribe = function (topic, func) {
if (! temas [tema]) {
temas [tema] = [];
}
var token = (++ Subuid) .ToString ();
Temas [tema] .push ({
Token: Token,
FUNC: FUNC
});
token de regreso;
};
// Método de falta de suscripción
Q.UnsubScribe = function (token) {
para (var m temas) {
if (temas [m]) {
para (var i = 0, j = temas [m] .length; i <j; i ++) {
if (temas [m] [i] .token === token) {
temas [m] .splice (i, 1);
token de regreso;
}
}
}
}
devolver falso;
};
} (pubSub));
Cómo usarlo es el siguiente:
La copia del código es la siguiente:
// Ven, suscríbete a uno
pubSub.subscribe ('Ejemplo1', function (temas, datos) {
console.log (temas + ":" + datos);
});
// Aviso de liberación
pubSub.publish ('Ejemplo1', '¡Hola mundo!');
pubSub.publish ('Ejemplo1', ['Test', 'A', 'B', 'C']);
pubSub.publish ('Ejemplo1', [{'Color': 'Blue'}, {'Text': 'Hello'}]);
¿Qué tal? ¿No es muy bueno usarlo? Pero hay un problema con este método, es decir, no hay forma de darse de baja. Si desea darse de baja, debe especificar el nombre de la suscripción, así que vayamos a otra versión:
La copia del código es la siguiente:
// Asigna la suscripción a una variable para dar a luz
var testSubscription = pubSub.subscribe ('Ejemplo1', function (temas, datos) {
console.log (temas + ":" + datos);
});
// Aviso de liberación
pubSub.publish ('Ejemplo1', '¡Hola mundo!');
pubSub.publish ('Ejemplo1', ['Test', 'A', 'B', 'C']);
pubSub.publish ('Ejemplo1', [{'Color': 'Blue'}, {'Text': 'Hello'}]);
// Descripción
setTimeOut (function () {
pubSub.UnsubScribe (TestSubscription);
}, 0);
// publicar nuevamente para verificar si la información aún se puede obtener
pubSub.publish ('Ejemplo1', '¡Hola de nuevo! (Esto fallará)');
Versión 2
También podemos usar las características del prototipo para implementar un patrón de observador, el código es el siguiente:
La copia del código es la siguiente:
function observver () {
this.fns = [];
}
Observador.prototype = {
suscríbete: function (fn) {
this.fns.push (fn);
},
Underscribe: function (fn) {
this.fns = this.fns.filter (
función (el) {
if (el! == fn) {
regresar el;
}
}
);
},
Actualización: function (o, thisObj) {
Var alcance = thisObj || ventana;
this.fns.foreach (
función (el) {
el.call (alcance, o);
}
);
}
};
//prueba
var o = nuevo observador;
var f1 = function (data) {
console.log ('Robbin:' + data + ', ¡trabaje rápidamente!');
};
var f2 = function (data) {
Console.log ('randall:' + data + ', ¡encuéntralo para obtener un salario adicional!');
};
O.Subscribe (F1);
O.Subscribe (F2);
o.update ("Tom está de vuelta!")
// Unta la suscripción a F1
o.unsubscribe (F1);
// Verifique de nuevo
o.update ("Tom está de vuelta!");
Si no se encuentra la función Filtro o ForEach, puede deberse a que su navegador no es lo suficientemente nuevo y no admite nuevas funciones estándar por el momento. Puedes definirlo tú mismo de la siguiente manera:
La copia del código es la siguiente:
if (! Array.prototype.ForEach) {
Array.prototype.forEach = function (fn, thisObj) {
Var alcance = thisObj || ventana;
para (var i = 0, j = this.length; i <j; ++ i) {
fn.call (alcance, este [i], i, esto);
}
};
}
if (! Array.prototype.filter) {
Array.prototype.filter = function (fn, thisObj) {
Var alcance = thisObj || ventana;
var a = [];
para (var i = 0, j = this.length; i <j; ++ i) {
if (! fn.call (alcance, este [i], i, esto)) {
continuar;
}
a.push (este [i]);
}
regresar a;
};
}
Versión 3
Si desea que múltiples objetos tengan la función de la suscripción de Publishing Observer, podemos definir una función común y luego aplicar la función de la función al objeto que requiere la función Observer. El código es el siguiente:
La copia del código es la siguiente:
// Código universal
var observador = {
//suscripción
addSubSCriber: function (devolución de llamada) {
this.
},
// Descripción
RemoveSubsCriber: function (devolución de llamada) {
para (var i = 0; i <this.subscrips.length; i ++) {
if (this.subscrips [i] === Callback) {
eliminar (this.subscrips [i]);
}
}
},
//liberar
publicar: function (what) {
para (var i = 0; i <this.subscrips.length; i ++) {
if (typeof this.subscrips [i] === 'function') {
this.
}
}
},
// hacer objeto o tener la función observador
Make: function (o) {
para (var i en esto) {
o [i] = this [i];
o.subscrips = [];
}
}
};
Luego, suscríbase a 2 objetos Blogger y usuario, use el método Observer.make para que estos dos objetos tengan funciones de Observer, el código es el siguiente:
La copia del código es la siguiente:
var blogger = {
Recomendar: function (id) {
var msg = 'dudu Publicación recomendada:' + id;
this.Publish (MSG);
}
};
user var = {
Vote: function (id) {
var msg = 'alguien votado! id =' + id;
this.Publish (MSG);
}
};
observador.make (blogger);
observador.make (usuario);
El método de uso es relativamente simple. Suscríbase a diferentes funciones de devolución de llamada para que pueda registrarse con diferentes objetos de Observer (o se pueden registrar múltiples objetos de Observer al mismo tiempo):
La copia del código es la siguiente:
var tom = {
Leer: Función (What) {
console.log ('Tom vio el siguiente mensaje:' + qué)
}
};
var mm = {
show: function (what) {
console.log ('mm vio el siguiente mensaje:' + qué)
}
};
// suscribir
Blogger.addsubsCriber (Tom.read);
Blogger.addsubScriber (mm.show);
Blogger.Recommend (123); // llamar a la publicación
// Descripción
Blogger.removesubScriber (mm.show);
Blogger.Recommend (456); // llamar a la publicación
// suscribirse a otro objeto
user.addsubsCriber (mm.show);
user.vote (789); // llamar a la publicación
versión jQuery
De acuerdo con la función de encendido/apagado agregada en jQuery versión 1.7, también podemos definir el observador de la versión jQuery:
La copia del código es la siguiente:
(función ($) {
var o = $ ({});
$ .subscribe = function () {
o.on.apply (o, argumentos);
};
$ .unsubscribe = function () {
O.Off.Apply (o, argumentos);
};
$ .publish = function () {
O.Grigger.apply (o, argumentos);
};
} (jQuery));
El método de llamadas es más simple que las tres versiones anteriores:
La copia del código es la siguiente:
// función de devolución de llamada
Function Handle (E, A, B, C) {
// `e` es un objeto de evento, no se requiere atención
console.log (a + b + c);
};
//suscripción
$ .subscribe ("/Some/Topic", Handle);
//liberar
$ .publish ("/Some/Topic", ["A", "B", "C"]); // Salida ABC
$ .UnsubScribe ("/Some/Topic", Handle); // cancelar la suscripción
//suscripción
$ .Subscribe ("/Some/Topic", Function (E, A, B, C) {
console.log (a + b + c);
});
$ .publish ("/Some/Topic", ["A", "B", "C"]); // Salida ABC
// Unscrite (Unsubscribe usa el nombre/Some/Topic, no la función de devolución de llamada, que es diferente del ejemplo de la versión 1
$ .unsubscribe ("/Some/Topic");
Se puede ver que su suscripción y su suscripción usan los nombres de las cadenas, no los nombres de las funciones de devolución de llamada, por lo que incluso si se pasa la función anónima entrante, podemos cancelar la suscripción.
Resumir
El uso de observadores es: cuando un objeto cambia para cambiar otros objetos al mismo tiempo y no sabe cuántos objetos deben cambiarse, debe considerar usar el modo Observer.
En general, lo que hace el patrón del observador es desacoplar, haciendo que ambos lados del acoplamiento se basen en la abstracción en lugar de el concreto. Esto hace posible que los cambios entre sí no afecten los cambios en el otro lado.