觀察者模式主要由一個目標對象(Subject)和一系列觀察者(Observer)組成,若是目標對象發生改變,目標就會通知對應的觀察者,每一個觀察者接收到通知後作出本身的變化。一個目標對象(Subject)能夠管理本身的觀察者(Observer),而且具備通知的方法,下面咱們用代碼來實現。html
// 觀察者列表,能夠對觀察者進行增長,修改等操做 // Subject會用到ObserverList來管理觀察者 function ObserverList() { this.observerList = []; } ObserverList.prototype.Add = function(obj){ // body... return this.observerList.push(obj); }; ObserverList.prototype.Empty = function(){ // body... this.observerList = []; }; ObserverList.prototype.Count = function(){ // body... return this.observerList.length; }; ObserverList.prototype.Get = function(index){ // body... if(index > -1 && index < this.observerList.length) { return this.observerList[index] } }; ObserverList.prototype.Insert = function(obj , index){ // body... var pointer = -1; if(index === 0) { this.observerList.unshift(obj); } if(index === this.observerList.length) { this.observerList.push(obj); } pointer = index; this.observerList.splice(index,0,obj); return pointer; }; ObserverList.prototype.IndexOf = function(obj, startIndex){ // body... 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){ // body... if( index === 0 ) { this.observerList.shift() } if( index === this.observerList.length ) { this.observerList.pop() } this.observerList.splice(index,1); };
目標對象利用ObserverList來管理觀察者,並具備通知的方法app
//目標 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 = observerCount - 1; i >= 0; i--) { // 收到通知後調用觀察者的Update方法 this.observers.Get(i).Update(context) } };
觀察者具備一個Update方法,每一個觀察者根據本身的業務來重寫Update方法,dom
function Observer() { this.Update = function() { console.log('默認實現') } }
最後實現一個extend方法,來擴展對象this
// 擴展obj對象 function extend(extension, obj) { for(var key in extension) { obj[key] = extension[key]; } }
這樣,觀察者模式就實現了,下面咱們用實際的例子來講明一下觀察者模式的用法。prototype
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <!-- 按鈕,每次點擊會增長一個checkbox,每一個checkbox都是一個觀察者(Observer) --> <button id="addNewObserver"> Add New Observer checkbox</button> <!-- 目標對象Subject,每次點擊後會把checked的值用通知發出去 --> <input type="checkbox" id="mainCheckbox"> <!-- 容器,新增的checkbox會放在該容器中 --> <div id="observerContainer"></div> <script> // 引用DOM var controlCheckbox = document.getElementById('mainCheckbox'); var addButton = document.getElementById('addNewObserver'); var container = document.getElementById('observerContainer'); // 具體目標 // 利用目標擴展 controlCheckbox extend(controlCheckbox, new Subject() ); // 點擊checkbox會觸發通知到觀察者 // 在Subject添加點擊事件,點擊後會將checked的值通知出去 controlCheckbox.addEventListener('click', new Function("controlCheckbox.Notify(controlCheckbox.checked)")) // 添加觀察者按鈕點擊事件 addButton.addEventListener('click', addNewObserver); // 具體觀察者 function addNewObserver() { //建立須要添加的checkbox var check = document.createElement("input"); check.type = 'checkbox'; // 將新增的checkbox變爲一個觀察者 extend(check, new Observer()); // 重寫Update方法 check.Update = function (value) { check.checked = value; } // subject將observer加入隊列 controlCheckbox.AddObserver(check); // 將dom加到容器中 container.appendChild(check) } </script> </body> </html>
運行後的效果你們能夠本身去嘗試一下,新增的checkBox的勾選狀態會和第一個checkBox,也就是Subject保持一致。code