前言: 如有错误和遗漏,欢迎通过kencall@163.com 联系我
Observer JavaScript Design Pattern 观察者模式Observer是一种设计模式,其中,一个对象,称为subject维持一系列依赖于它(观察者)的对象,将有关状态的任何变更自动通知给它们。
网上很多人将观察者模式与发布订阅模式(Publish/Subscribe)进行混淆。它们之间确实有很多相同点,但是在设计上还是有很大不同。
ok,废话不多说。看javaScript设计模式中的代码:
构建Observer的CRUD 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 function ObserverList ( ) { this .observerList = [] } ObserverList.prototype.Add = function (obj ) { return this .observerList.push(obj) } ObserverList.prototype.Empty = function ( ) { this .observerList = [] } ObserverList.prototype.Count = function ( ) { return this .observerList.length } ObserverList.prototype.Get = function (index ) { if (index > -1 && index < this .observerList.length) { return this .observerList[index] } } ObserverList.prototype.Insert = function (obj,index ) { var pointer = -1 ; if (index === 0 ) { this .observerList.unshift(obj) pointer = index; }else if (index === this .observerList.length) { this .observerList.push(obj) pointer = index; } return pointer } ObserverList.prototype.IndexOf = function (obj, startIndex ) { var i = startIndex, pointer = -1 ; while (i< this .observerList.length) { if (this .observerList[i] === obj) { pointer = i; } i++ } return pointer } ObserverList.prototype.RemoveIndexAt = function (index ) { if (index === 0 ) { this .observerList.shift() }else if (index === this .observerList.length-1 ) { this .observerList.pop() }else { var reset = this .observerList.slice(index + 1 ); this .observerList.length = index < 0 ? this .observerList.length + index : index; this .observerList = this .observerList.concat(reset) } } function extend (obj, extension ) { for (var key in obj) { extension[key] = obj[key] } }
subject对observer的CRUD 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function Subject ( ) { this .observers = new ObserverList; } Subject.prototype.AddObserver = function (observer ) { this .observers.Add(observer) } Subject.prototype.RemoveObserver = function (observer ) { this .observers.RemoveIndexAt(this .observers.IndexOf(observer, 0 )) } Subject.prototype.Notify = function (context ) { var observerCount = this .observers.Count() for (var i = 0 ; i< observerCount; i++) { this .observers.Get(i).Update(context) } }
实际应用1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 <!DOCTYPE html> <html lang ="en" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <meta http-equiv ="X-UA-Compatible" content ="ie=edge" > <title > Document</title > </head > <body > <button id ="addNewObserver" > Add New observer checkbox</button > <input id ="mainCheckbox" type ="checkbox" /> <div id ="observersContainer" > </div > <div id ="observerControl" > </div > <script src ="./observer.js" > </script > <script > var controlCheckBox = document .getElementById('mainCheckbox' ), addObserverBtn = document .getElementById('addNewObserver' ), container = document .getElementById('observerContainer' ) extend(new Subject(), controlCheckbox) controlCheckbox["onclick" ] = new Function ("controlCheckbox.Notify(controlCheckbox.checked)" ) function Observer ( ) { this .Update = function ( ) { } } function AddNewObserver ( ) { var check = document .createElement('input' ) check.type="checkbox" extend(new Observer(), check) check.Update = function (value ) { this .checked = value; } controlCheckbox.AddObserver(check) container.appendChild(check) } addObserverBtn["onclick" ] = AddNewObserver </script > </body > </html >
实际应用2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 <!DOCTYPE html> <html lang ="en" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <meta http-equiv ="X-UA-Compatible" content ="ie=edge" > <title > Document</title > </head > <body > <div id ="subject" > 我是具体目标</div > <div id ="observer1" > 我是观察者1</div > <div id ="observer2" > 我是观察者2</div > <div id ="observer3" > 我是观察者3</div > <div id ="cancalObserver" > 解除第二个观察者</div > </body > </html > <script src ="./observer.js" > </script > <script > let subject = document .getElementById('subject' ), observer1 = document .getElementById('observer1' ), observer2 = document .getElementById('observer2' ), observer3 = document .getElementById('observer3' ), cancalObserver = document .getElementById('cancalObserver' ); extend(new Subject(), subject); subject.addEventListener('click' ,function ( ) { subject.Notify('明天放假一天' ) }) function Observer ( ) { this .Update= function ( ) {} } subject.AddObserver(observer1) subject.AddObserver(observer2) subject.AddObserver(observer3) observer1.Update= function (acceptInfo ) { console .log(acceptInfo+'-- 好的,观察者一收到' ) } observer2.Update= function (acceptInfo ) { console .log(acceptInfo+'-- 好的,观察者二收到' ) } observer3.Update= function (acceptInfo ) { console .log(acceptInfo+'-- 好的,观察者三收到' ) } cancalObserver.addEventListener('click' , function ( ) { subject.RemoveObserver(observer2), console .log('观察者二解除观察----》》》' ) }) </script >
总结 那么最后:什么是观察者模式—> :
首先要定义一个subject目标源,监听某一事件->触发subject.Notify(->触发observer.Update())
定义具体的observer,考虑事件是否可抽象->(subject发布信息后,观察者具体需要做的事情)
给subject添加具体的observer
观察者模式 The observer pattern is a software design pattern in which an object, called the subject , maintains a list of its dependents, called observers , and notifies them automatically of any state changes, usually by calling one of their methods.
subject触发某一事件的时候,会自动发布事件给它的观察者。这个观察者不需要监听某一事件.但是suject必须显示地添加其观察者
发布/订阅模式 In ‘Publisher-Subscriber’ pattern, senders of messages, called publishers , do not program the messages to be sent directly to specific receivers, called subscribers.
而发布者不必知道订阅者是谁,只需要将事件发布到一个“中间件”,由中间件去处理订阅者的不同需求