The observer pattern is also called the Publish-subscribe pattern, which defines a one-to-many dependency between objects, and all objects that depend on it will be notified when the state of an object changes. In JavaScript, the event model is generally used instead of the traditional observer pattern.
The following is an example of the sales Office (publisher) and the individual viewing (subscribers):
var event = {
Clientlist:[],//Cache list
Listen:function (KEY,FN) {//Add Subscribers
if (!this.clientlist[key]) {
This.clientlist[key] = [];
}
This.clientlist[key].push (FN); Subscribed messages are added to the cache list
},
Trigger:function () {//Publish message
var key = Array.prototype.shift.call (arguments),
FNS = This.clientlist[key];
if (!fns | | fns.length = = 0) {//does not have a message corresponding to the binding
return false;
}
for (var i=0,fn; fn=fns[i++]) {
Fn.apply (this, arguments);
}
},
Remove:function (KEY,FN) {//delete subscription
var FNS = This.clientlist[key];
if (!FNS) {//if the message corresponding to the key is not subscribed by the person, it is returned directly
return false;
}
if (!FN) {//If no specific callback function is passed, all subscriptions that need to cancel the key corresponding message are
FNS && (fns.length = 0);
}else{
for (var l=fns.length-1; l>=0; l--) {//The list of callback functions for the reverse traversal subscription
var _fn = fns[l];
if (_fn ===fn) {
Fns.splice (l,1); Remove a subscriber's callback function
}
}
}
}
};
var installevent = function (obj) {//dynamically install publish-subscribe functionality for all objects
for (var i in event) {
Obj[i] = Event[i];
}
};
var salesoffices = {}; Define Sales Office
Installevent (salesoffices);
Salesoffices.listen (' squareMeter100 ', function (price) {//Zhang San subscription message
Console.log (' prices = ' + price);
});
Salesoffices.listen (' squareMeter150 ', function (price) {//John Doe subscription message
Console.log (' prices = ' + price);
});
Salesoffices.trigger (' squareMeter100 ', 2000000); Output 2000000
Salesoffices.trigger (' squareMeter150 ', 3000000); Output 3000000
The above code also has two minor problems:
1. Each Publisher object adds the listen and trigger methods, and a cache list clientlist, which is a waste of resources
2. Subscribers and sales Office objects have some coupling, subscribers should at least know the name of the sales Office object is salesoffices, to subscribe to the event
The following are improvements to the above two issues:
var event = {
var clientlist:[],
Listen
Trigger
Remove
Listen = function (KEY,FN) {
if (!clientlist[key]) {
Clientlist[key] = [];
}
Clientlist[key].push (FN); Subscribed messages are added to the cache list
};
Trigger = function () {//Publish message
var key = Array.prototype.shift.call (arguments),
FNS = Clientlist[key];
if (!fns | | fns.length = = 0) {//does not have a message corresponding to the binding
return false;
}
for (var i=0,fn; fn=fns[i++]) {
Fn.apply (this, arguments);
}
};
remove = function (KEY,FN) {//delete subscription
var FNS = Clientlist[key];
if (!FNS) {//if the message corresponding to the key is not subscribed by the person, it is returned directly
return false;
}
if (!FN) {//If no specific callback function is passed, all subscriptions that need to cancel the key corresponding message are
FNS && (fns.length = 0);
}else{
for (var l=fns.length-1; l>=0; l--) {//The list of callback functions for the reverse traversal subscription
var _fn = fns[l];
if (_fn ===fn) {
Fns.splice (l,1); Remove a subscriber's callback function
}
}
}
};
return {
Listen:listen,
Trigger:trigger,
Remove:remove
};
};
Event.listen (' squareMeter150 ', function (price) {//John Doe subscription message
Console.log (' prices = ' + price);
});
Event.trigger (' squareMeter150 ', 2000000); Output 2000000
After the improvement, the publish-subscribe mode can be implemented with a global event object, the Subscriber does not need to know which publisher the message comes from, and the publisher does not need to know which subscribers the message will be pushed to, and the event acts as a "mediator" role, linking subscribers and publishers.
The advantages of the observer pattern are very obvious, one is the decoupling of the time and the other is the decoupling between the two objects. It can be used in asynchronous programming or in writing more loosely coupled code. But it is not without shortcomings. Creating the subscriber itself consumes a certain amount of time and memory, and when you subscribe to a message, perhaps this message never happens, but the Subscriber will always be in memory. In addition, the observer pattern can weaken the relationship between objects, but if overused, the necessary connections between objects will be hidden behind, which will make the program difficult to track maintenance and understanding. Especially when there are multiple publishers and subscribers nested together, to track a bug is not a key easy thing.
JavaScript Viewer mode