觀察者模式:
觀察者模式是設(shè)計(jì)模式的一種:由一個(gè)目標(biāo)實(shí)體(事件發(fā)送者)來維護(hù)一組的觀察者静稻,并自動(dòng)把它們的狀態(tài)改變通知觀察者。
實(shí)現(xiàn)它需要一下幾個(gè)部分:
- Subject: 目標(biāo)
包含觀察者序列類鸿竖,包括對觀察者的增加和刪除等功能煮盼, - Observer: 觀察者
定義Update接口凄吏,根據(jù)Subject狀態(tài)定義不同函數(shù)远舅,如
C#中對觀察者接口的定義
public interface IObserver<in T>
{
void OnCompleted ();
void OnError (Exception error);
void OnNext (T value);
}
- ConcreteSubject: 具體目標(biāo)(Subject的子類)
把狀態(tài)變化廣播通知給所有具體觀察者,保存具體觀察者的狀態(tài) - ConcreteObserver: 具體觀察者(Observer的子類)
存儲ConcreteSubject的引用(隨時(shí)知道具體目標(biāo)的狀態(tài)發(fā)生改變)痕钢,實(shí)現(xiàn)各種狀態(tài)對應(yīng)的Update方法使?fàn)顟B(tài)與具體目標(biāo)保持一致
javascript 實(shí)現(xiàn)
- 觀察者序列建模图柏,實(shí)現(xiàn)一個(gè)observerList,包括方法:Add任连,Empty蚤吹,Count,Get随抠,Insert距辆,IndexOf余佃,RemoveIndexAt
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();
}
};
// Extend an object with an extension
//可以給觀察者添加事件函數(shù)
function extend( extension, obj ){
for ( var key in extension ){
obj[key] = extension[key];
}
}
- 實(shí)現(xiàn)一個(gè)管理ObserverList的目標(biāo)
function Subject(){
this.observers = new ObserverList();
}
Subject.prototype.AddObserver = function( observer ){
this.observers.Add( observer );
};
Subject.prototype.RemoveObserver = function( observer ){
this.observers.RemoveAt( 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 );
}
};
- 聲明一個(gè)觀察者暮刃,Update方法可以被根據(jù)具體的客戶行為重新
// The Observer
function Observer(){
this.Update = function(){
// ...
};
}
測試代碼:
html
<button id="addNewObserver">Add New Observer checkbox</button>
<input id="mainCheckbox" type="checkbox"/>
<div id="observersContainer"></div>
** 腳本代碼**
// References to our DOM elements
var controlCheckbox = document.getElementById( "mainCheckbox" ),
addBtn = document.getElementById( "addNewObserver" ),
container = document.getElementById( "observersContainer" );
// Concrete Subject
// Extend the controlling checkbox with the Subject class
extend( new Subject(), controlCheckbox );
// Clicking the checkbox will trigger notifications to its observers
controlCheckbox["onclick"] = new Function( "controlCheckbox.Notify(controlCheckbox.checked)" );
addBtn["onclick"] = AddNewObserver;
// Concrete Observer
function AddNewObserver(){
// Create a new checkbox to be added
var check = document.createElement( "input" );
check.type = "checkbox";
// Extend the checkbox with the Observer class
extend( new Observer(), check );
// Override with custom update behaviour
check.Update = function( value ){
this.checked = value;
};
// Add the new observer to our list of observers
// for our main subject
controlCheckbox.AddObserver( check );
// Append the item to the container
container.appendChild( check );
}