本系列教程不會講得特別深,經過案例,就帶個入門,面試的時候,被問到能答出個因此來,在實際運用中,能把複雜的問題簡單化就夠了。javascript
你們應該常常聽到工廠模式,單體模式,可是,可能你們可能第一次據說觀察者模式,因此我設計模式系列第一篇就來說講觀察者模式。相信你們都用過鼠標懸停,按鍵等事件,其實他們就是觀察者模式的例子。說重點,這種模式的實質就是你能夠對程序中的某個對象的狀態進行觀察,而且在其發生改變時可以獲得通知。html
觀察者模式中存在兩種角色:觀察者和被觀察者,也能夠叫作發佈者和訂閱者。java
例如,你在你每一個階段,進行到必定階段的時候,就要作一些事情,就能夠利用觀察者模式作一些相應的處理,不過多解釋了。git
觀察者模式中,並非一個對象調用另外一個對象的方法,而是一個對象訂閱另外一個對象的特定活動並在狀態改變後得到通知。當發生了一個重要的事件時,發佈者將會通知全部訂閱者而且可能常常以事件對象的形式傳遞消息。github
爲了加深理解,讓咱們來看一個具體的例子,有三個報紙出版社,報社1、報社2、報社三,有兩個訂報人,分別是:訂閱者1,訂閱者2。在這裏出版社就是被觀察者,訂報人就是觀察者面試
//觀察者模式:對程序中某一個對象的進行實時的觀察,當該對象狀態發生改變的時候 進行通知
//被觀察者
var Publish = function (name) {
this.name = name;
this.subscribers = []//數組中存着全部的訂閱者(出版社名單),數組的元素都是函數類型
}
//publish的實例對象去發佈消息的方法
Publish.prototype.deliver = function (news) {
var publish = this;//this就表明報社
this.subscribers.forEach(function (item) {
//循環subscribers數組中全部的訂報人,爲他們發佈內容。
item(news,publish);//每一個訂閱者都收到了新聞(news),還有來自哪家報刊
})
return this;//爲了方便,採用鏈式調用。
}複製代碼
訂閱功能設計模式
//訂閱者的方法,每個訂閱者都是一個函數,在函數原型上擴展一個方法
Function.prototype.subscribe = function (publish) {//出版社形參
var sub = this;//取得當前訂閱者這我的
//不能同時訂一家出版社同一份報紙,沒意義
//publish.subscribers//張三,李四,王五,名字可能重複
//publish.subscribers數組裏面有的人,不能再訂閱
//咱們使用ecma5裏面的some方法,循環遍歷數組的每個元素,執行一個函數,若是有相同的名字則返回true,不相同則返回false
var alreadExists = publish.subscribers.some(function (item) {
return item ===sub;
})
//若是出版社名單沒有這我的,則加入其中
if(!alreadExists){
publish.subscribers.push(sub);
}
return this;//爲了方便,採用鏈式調用。
}複製代碼
取消訂閱數組
//具體的一個訂閱者去取消訂閱報紙的方法
Function.prototype.unsubscribe = function(publish){
var sub = this;//取得當前訂閱者這我的
// filter (過濾函數:循環便利數組的每個元素,執行一個函數若是不匹配,則刪除該元素)
publish.subscribers = publish.subscribers.filter(function(item){
return item !== sub ;
});
return this;//爲了方便,採用鏈式調用。
};複製代碼
好了,上面就已經作好了基本的準備的,咱們來作個小demo函數
//實例化發佈者對象(報社對象)
var pub1 = new Publish('報社一');
var pub2 = new Publish('報社二');
var pub3 = new Publish('報社三');
//觀察者
var sub1 = function (news,pub) {
console.log(arguments);
document.getElementById('sub1').innerHTML +=pub.name+ news +'\n'
}
var sub2 = function (news,pub) {
document.getElementById('sub2').innerHTML += pub.name+news+'\n'
}
var p1 = document.getElementById('pub1')
var p2 = document.getElementById('pub2')
var p3 = document.getElementById('pub3')
//執行訂閱方法
sub1.subscribe(pub1).subscribe(pub2).subscribe(pub3)
sub2.subscribe(pub1).subscribe(pub2).subscribe(pub3)
//事件綁定
p1.onclick = function () {
pub1.deliver(document.getElementById('text1').value,pub1);
}
p2.onclick = function () {
pub2.deliver(document.getElementById('text2').value,pub2);
}
p3.onclick = function () {
pub3.deliver(document.getElementById('text3').value,pub3);
}
sub1.unsubscribe(pub1); //取消訂閱複製代碼
咱們來看看html代碼段ui
<div class="col-lg-8">
<div class="input-group"> <span id="pub1" class="input-group-addon"> 報社一 </span> <input v-model="user.name" type="text" class="form-control" id="text1"> </div> </div>
<div class="col-lg-8">
<div class="input-group"> <span id="pub2" class="input-group-addon"> 報社二 </span> <input v-model="user.name" type="text" class="form-control" id="text2"> </div> </div>
<div class="col-lg-8">
<div class="input-group"> <span id="pub3" class="input-group-addon"> 報社三 </span> <input v-model="user.name" type="text" class="form-control" id="text3"> </div> </div>
<div class="col-lg-8">
訂閱者一
<textarea id="sub1" class="form-control" rows="5"></textarea>
訂閱者二:
<textarea id="sub2"class="form-control" rows="5"></textarea>
</div>複製代碼
不知道大家看懂了嗎?沒看懂能夠隨時留言,後續會出這一系列關於js設計模式的文章,大概有十章左右,包括單體模式,外觀模式,中介者模式等等,由簡單到難(歡迎留言這一篇看的感覺),因此歡迎你們指正,批評,督促。
github源碼地址:github.com/Faithree/js…
參照案例書籍javascript模式
點贊是個人最大支持和鼓勵