introduire
Le mode observateur est également appelé Publish / Subscribe. Il définit une relation un-à-plusieurs, permettant à plusieurs objets d'observateurs d'écouter un objet de sujet en même temps. Lorsque l'état de ce sujet change, tous les objets d'observateurs seront informés, afin qu'ils puissent se mettre à jour automatiquement.
Avantages de l'utilisation du mode observateur:
1. Prend en charge la communication de diffusion simple et informe automatiquement tous les objets abonnés.
2. Une fois la page chargée, l'objet cible peut facilement avoir une corrélation dynamique avec l'observateur, ce qui augmente la flexibilité.
3. La relation de couplage abstraite entre l'objet cible et l'observateur peut être élargie et réutilisée séparément.
Texte (version 1)
La mise en œuvre du modèle d'observateur dans JS est réalisée grâce à des rappels. Définissons d'abord un objet PubSub, qui contient 3 méthodes: abonnement, désabonnement et publication.
La copie de code est la suivante:
var pubsub = {};
(fonction (q) {
var sujets = {}, // Array stocké par la fonction de rappel
subuid = -1;
// Publier la méthode
q.publish = fonction (sujet, args) {
if (! sujets [thème]) {
retourne false;
}
setTimeout (function () {
Var abonnés = sujets [Sujet],
Len = abonnés? abonnés.length: 0;
while (len--) {
abonnés [len] .func (sujet, args);
}
}, 0);
Retour Vrai;
};
// Méthode d'abonnement
Q.Subscribe = fonction (sujet, func) {
if (! sujets [thème]) {
sujets [sujet] = [];
}
var token = (++ subuid) .toString ();
sujets [thème] .push ({
Token: jeton,
Func: Func
});
Token de retour;
};
// Méthode de désinscription
q.unSubscribe = fonction (jeton) {
pour (var m dans les sujets) {
if (sujets [m]) {
pour (var i = 0, j = sujets [m] .length; i <j; i ++) {
if (sujets [m] [i] .token === Token) {
sujets [m] .splice (i, 1);
Token de retour;
}
}
}
}
retourne false;
};
} (pubsub));
Comment l'utiliser est comme suit:
La copie de code est la suivante:
// venez, abonnez-vous à un
pubsub.subscribe ('example1', fonction (sujets, données) {
console.log (sujets + ":" + données);
});
// Avis de libération
pubsub.publish («Exemple1», «Hello World!»);
pubsub.publish («example1», [«test», «a», «b», «c»]);
pubsub.publish ('example1', [{'Color': 'Blue'}, {'Text': 'Hello'}]);
Et ça? N'est-ce pas très bon à utiliser? Mais il y a un problème avec cette méthode, c'est-à-dire qu'il n'y a aucun moyen de se désabonner. Si vous souhaitez vous désinscrire, vous devez spécifier le nom de la désabonnement, alors allons à une autre version:
La copie de code est la suivante:
// attribue l'abonnement à une variable à désabonner
var testSubScription = pubsub.subscribe ('example1', fonction (sujets, données) {
console.log (sujets + ":" + données);
});
// Avis de libération
pubsub.publish («Exemple1», «Hello World!»);
pubsub.publish («example1», [«test», «a», «b», «c»]);
pubsub.publish ('example1', [{'Color': 'Blue'}, {'Text': 'Hello'}]);
// non-subscription
setTimeout (function () {
pubsub.unSubscribe (TestSubscription);
}, 0);
// Publier à nouveau pour vérifier si les informations peuvent toujours être sorties
pubsub.publish («example1», «bonjour encore! (Cela échouera)»);
Version 2
Nous pouvons également utiliser les caractéristiques du prototype pour implémenter un modèle d'observateur, le code est le suivant:
La copie de code est la suivante:
Fonction Observer () {
this.fns = [];
}
Observer.prototype = {
abonnez-vous: fonction (fn) {
this.fns.push (fn);
},
désinscriptif: fonction (fn) {
this.fns = this.fns.filter (
fonction (el) {
if (el! == fn) {
Retour El;
}
}
));
},
Mise à jour: fonction (o, thisObj) {
var scope = thisObj || fenêtre;
this.fns.Forach (
fonction (el) {
El.Call (Scope, O);
}
));
}
};
//test
var o = nouvel observateur;
var f1 = fonction (data) {
Console.log ('Robbin:' + Data + ', travaille rapidement!');
};
var f2 = fonction (data) {
Console.log («Randall:« + Data + », trouvez-le pour obtenir un salaire supplémentaire!»);
};
O.Subscribe (F1);
O.Subscribe (F2);
O.update ("Tom est de retour!")
// se désinscrire à F1
O.UnSubscribe (F1);
//Revérifier
O.update ("Tom est de retour!");
Si le filtre ou la fonction foreach n'est pas trouvé, cela peut être dû au fait que votre navigateur n'est pas suffisamment nouveau et ne prend pas en charge les nouvelles fonctions standard pour le moment. Vous pouvez le définir vous-même de la manière suivante:
La copie de code est la suivante:
if (! array.prototype.ForEach) {
Array.prototype.ForEach = function (fn, thisObj) {
var scope = thisObj || fenêtre;
pour (var i = 0, j = this.length; i <j; ++ i) {
fn.Call (Scope, this [i], i, this);
}
};
}
if (! array.prototype.filter) {
Array.prototype.filter = fonction (fn, thisObj) {
var scope = thisObj || fenêtre;
var a = [];
pour (var i = 0, j = this.length; i <j; ++ i) {
if (! fn.call (scope, this [i], i, this)) {
continuer;
}
a.push (this [i]);
}
retourner a;
};
}
Version 3
Si vous souhaitez que plusieurs objets aient la fonction de l'abonnement à la publication d'observateurs, nous pouvons définir une fonction commune, puis appliquer la fonction de la fonction à l'objet qui nécessite une fonction d'observateur. Le code est le suivant:
La copie de code est la suivante:
// Code universel
var observateur = {
//abonnement
AddSubscriber: fonction (rappel) {
this.subscrirs [this.subscrirs.length] = callback;
},
// non-subscription
supprimer
for (var i = 0; i <this.subscrirs.length; i ++) {
if (this.subscrirs [i] === rappel) {
Delete (this.Subscrirs [i]);
}
}
},
//libérer
publier: fonction (quoi) {
for (var i = 0; i <this.subscrirs.length; i ++) {
if (typeof this.subscrirs [i] === 'function') {
this.subscripteurs [i] (quoi);
}
}
},
// Faire de l'objet o avoir une fonction d'observateur
faire: fonction (o) {
pour (var i dans ceci) {
o [i] = this [i];
O.Subscripteurs = [];
}
}
};
Ensuite, abonnez-vous à 2 objets Blogger et User, utilisez la méthode Observer.Make pour faire que ces deux objets ont des fonctions d'observateur, le code est le suivant:
La copie de code est la suivante:
var blogger = {
Recommande: fonction (id) {
var msg = 'Post recommandé par Dudu:' + id;
this.publish (msg);
}
};
var user = {
Vote: fonction (id) {
var msg = 'quelqu'un a voté! id =' + id;
this.publish (msg);
}
};
Observer.Make (blogueur);
Observer.Make (utilisateur);
La méthode d'utilisation est relativement simple. Abonnez-vous à différentes fonctions de rappel afin que vous puissiez vous inscrire avec différents objets d'observateurs (ou plusieurs objets d'observateurs peuvent être enregistrés en même temps):
La copie de code est la suivante:
var tom = {
lire: fonction (quoi) {
console.log ('Tom a vu le message suivant:' + quoi)
}
};
var mm = {
show: function (quoi) {
console.log ('mm a vu le message suivant:' + quoi)
}
};
// S'abonner
blogger.addsubscriber (tom.read);
blogger.addsubscriber (mm.show);
Blogger.Recommend (123); // Appel Publish
// non-subscription
Blogger.Removesubscriber (mm.show);
Blogger.Recommend (456); // Appel Publish
// Abonnez-vous à un autre objet
user.addsubscriber (mm.show);
user.vote (789); // Appel Publish
version jQuery
Selon la fonction ON / OFF ajoutée dans JQuery Version 1.7, nous pouvons également définir l'observateur de la version jQuery:
La copie de code est la suivante:
(fonction ($) {
var o = $ ({});
$ .subscribe = function () {
o.on.apply (o, arguments);
};
$ .unSubscribe = function () {
o.off.apply (o, arguments);
};
$ .publish = function () {
o.trigger.apply (o, arguments);
};
} (jQuery));
La méthode d'appel est plus simple que les trois versions ci-dessus:
La copie de code est la suivante:
// Fonction de rappel
Poignée de fonction (e, a, b, c) {
// `e` est un objet d'événement, aucune attention n'est requise
console.log (a + b + c);
};
//abonnement
$ .subscribe ("/ sweet / thème", manche);
//libérer
$ .Publish ("/ Some / Topic", ["A", "B", "C"]); // Sortie ABC
$ .unSubscribe ("/ Some / Topic", manche); // se désabonner
//abonnement
$ .subscribe ("/ some / thème", fonction (e, a, b, c) {
console.log (a + b + c);
});
$ .Publish ("/ Some / Topic", ["A", "B", "C"]); // Sortie ABC
// Disubscribe (Désubscribe utilise le nom / un autre nom, pas la fonction de rappel, qui est différente de l'exemple de la version 1
$ .unSubscribe ("/ Some / Topic");
On peut voir que son abonnement et son désabonnement utilisent des noms de chaîne, pas des noms de fonction de rappel, donc même si la fonction anonyme entrante est adoptée, nous pouvons nous désabonner.
Résumer
L'utilisation des observateurs est: lorsqu'un objet change pour changer d'autres objets en même temps et qu'il ne sait pas combien d'objets doivent être modifiés, il devrait envisager d'utiliser le mode observateur.
Dans l'ensemble, ce que fait le modèle d'observateur, c'est se découpler, ce qui fait que les deux côtés du couplage reposent sur l'abstraction plutôt que sur le béton. Cela permet que les changements les uns des autres n'affectent pas les changements de l'autre côté.