background
Definition of Design Patterns: A concise and elegant solution to a specific problem in the process of object-oriented software design.
Design patterns can not be used to write code directly, but to describe how to solve problems in different situations. It is not a dead mechanism, it is an idea, a form of code.
Each language has its own way of implementing various design patterns. For some design patterns, it may not be applicable in some languages, such as factory patterns, which are not applicable to JavaSctipt. Patterns should be used in the right place, and the so-called right place can only be known when we have a deep understanding of the intentions of the pattern and then combined with the actual scenario of the project.
Observer Pattern
The observer pattern defines one-to-many dependencies among objects. When the state of an object changes, all objects that depend on it will be notified and updated automatically.
The observer pattern belongs to the behavior pattern. The behavior pattern focuses on the communication between the objects. The observer pattern is the communication between the observer and the observee.
Observer mode has another alias called "Publish-Subscribe Mode" or "Subscribe-Publish Mode". Subscribers and subscription goals are linked. When subscription goals change, each subscriber is notified.
We use the subscription of newspapers and periodicals as an example. When you subscribe to a newspaper, a newest newspaper will be delivered to you every day. How many people subscribe to the newspaper, how many newspapers will be distributed by the newspaper. The newspaper and its subscribers are the "one-to-many" dependency described in the definition.
Pub-Sub Pattern
In fact, among the 24 basic design patterns, there is no publish-subscribe pattern. As explained above, it is just another name for the observer pattern. But after time, it has become strong, independent of the observer model, and become a new design model.
In the current publish-subscribe model, the message of the publisher is not sent directly to the subscriber, which means that neither the publisher nor the subscriber knows the existence of each other. There is a third component between publishers and subscribers, called message broker or scheduling center or middleware, which maintains the relationship between publishers and subscribers, filters messages from all publishers and distributes them to their subscribers accordingly.
For example, you pay attention to A on Weibo, while many other people also pay attention to A. When A publishes a dynamic, Weibo will push this dynamic for you. A is the publisher, you are the subscriber, Weibo is the dispatch center, you and A do not have direct information exchanges, all through Weibo to coordinate.
What's the difference between the observer model and the publish-subscribe model?
Let's first look at the implementation structure of the two modes:
Observer mode: Observer directly subscribes to Subscribe subject, which triggers events in Fire Event observer when the subject is activated.
Publish-Subscriber mode: Subscriber registers the event it wants to subscribe to to Topic. When Publisher publishes the event to the dispatch center, that is, when the event triggers, the processing code registered by Fire Event Subscriber to the dispatch center.
case
Observer model
// There's a hunter's guild where each Hunter publishes and subscribes specific functions. // They all have a subscription list that records who subscribed to them. // Define a hunter, including name, level, subscription list function Hunter(name, level) { this,name = name this.level = level this.list = [] } Hunter.prototype.publish = function (money) { console.log(this,level + 'Hunter: ' + this.name + 'Ask for help') this.list.forEach(function (callback) { callback && callback(money) }) } Hunter.prototype.subscribe = function (target, callback) { console.log(this.level + 'Hunter: ' + this.name + 'Subscribed: ' + target.name) target.list.push(callback) } // The Hunter's Guild registered several hunters. var hunterZhang = new Hunter('Zhang San', 'Diamonds') var hunterLi = new Hunter('Li Si', 'gold') var hunterWang = new Hunter('Wang Wu', 'silver') var hunterZhao = new Hunter('Zhao Liu', 'bronze') // Zhao Six has a lower rank and may need help, so Zhang San, Li Si and Wang Wudu subscribed to Zhao Six. hunterZhang.subscribe(hunterZhao, function (money) { console.log('Xiao Ming said: ' + (money > 200 ? '' : 'I'm busy for the time being, but I can't.') + 'Give help') }) hunterLi.subscribe(hunterZhao, function () { console.log('Li Sizheng: Give help') }) hunterWang.subscribe(hunterZhao, function () { console.log('Wang Wuyi: Give help') }) // Zhao Liuyu was confronted with difficulties. He offered a reward for 198 to seek help. hunterZhao.publish(198) // Hunters (observers) associate with hunters (targets) they are interested in, such as Zhao Liu. When Zhao Liu has difficulties, they will be notified automatically.
Publish-Subscribe Mode
// Define a Hunter's Guild // The main functions include task publishing hall (topics), subscribe task (subscribe), publish task (publish). var HunterUnion = { type: 'hunt', topics: Object.create(null), subscribe: function (topic, callback) { if (!this.topics[topic]) { this.topics[topic] = [] } this.topics[topic].push(callback) }, publish: function (topic, money) { if (!this.topics[topic]) { return } for(var cb of this.topics[topic]) { cb(money) } } } // Define a hunter, including name and rank function Hunter(name, level) { this.name = name this.level = level } // Hunters can publish and subscribe to quests at the Hunters Guild. Hunter.prototype.subscribe = function (task, fn) { console.log(this.level + 'Hunter: ' + this.name + 'Subscribed to hunting: ' + task + 'Tasks') HunterUnion.subscribe(task, fn) } Hunter.prototype.publish = function (task, money) { console.log(this.level + 'Hunter: ' + this.name + 'The hunting was released.: ' + task + 'Tasks') HunterUnion.publish(task, money) } //The Hunter's Union registered several hunters. let hunterZhang = new Hunter('Zhang San', 'Diamonds') let hunterLi = new Hunter('Li Si', 'gold') let hunterWang = new Hunter('Wang Wu', 'silver') let hunterZhao = new Hunter('Zhao Liu', 'bronze') //Zhang San, Li Si and Wang Wu subscribed to the task of hunting tiger respectively. hunterZhang.subscribe('tiger', function(money){ console.log('Zhang San said:' + (money > 200 ? '' : 'No') + 'Acceptance Task') }) hunterLi.subscribe('tiger', function(money){ console.log('Li Si said: Take over the task') }) hunterWang.subscribe('tiger', function(money){ console.log('Wang Wu said: Take over the task') }) //Zhao Liu subscribed to the task of hunting sheep. hunterZhao.subscribe('sheep', function(money){ console.log('Zhao Liu said: Take over the task') }) //Zhao Liu released the mission of hunting tiger hunterZhao.publish('tiger', 198) //Hunters publish (publisher) or subscribe (observer/subscriber) tasks are linked through hunters'unions (dispatch centers), and they do not have direct communication.
The biggest difference between the observer model and the publish-subscribe model is that the publish-subscribe model has an event scheduling center.
The observer mode is scheduled by specific targets, and each subscribed target needs to be processed by the observer, which may cause code redundancy.
In publish-subscribe mode, it is processed by scheduling. Subscribers and publishers do not interfere with each other, eliminating the dependence between publishers and subscribers. On the one hand, it realizes decoupling, on the other hand, it can achieve more fine-grained control. For example, the publisher publishes a lot of messages, but not all subscribers want to receive them, so they can do some processing in the dispatch center, such as privilege control. There are also some throttling operations.
Is the Observer mode a Publish-Subscribe mode?
The book JavaScript Design Patterns and Development Practices says that the key to distinguishing patterns is intention rather than structure.
If the structure is used to distinguish the mode, the publish-subscribe mode has one more scheduling center than the observer mode, so the publish-subscribe mode is different from the observer mode.
If patterns are distinguished by intention, they all realize one-to-many dependencies among objects. When the state of an object changes, all objects depending on it will be notified and updated automatically. Then they are the same pattern. Publish-subscribe mode is optimized and upgraded on the basis of observer mode. .
However, whether they are the same design pattern or not, there are differences in the way they are implemented. When we use them, we should decide which to choose according to the application scenario.