Идея паттерна Observer заключается в создании зависимости типа один ко многим. При изменении состояния одного объекта(субъекта), зависящие от него объекты(наблюдатели) об этом оповещаются и обновляются. Это нужно для согласования состояния взаимосвязанных объектов без их жесткой связанности.
Например, при изменении данных A, B, C диаграмма и таблица, отвечающие за представление, должны измениться. При этом неизвестно, сколько имеется представлений.

Паттерн наблюдатель описывает, как реализовать такое отношение. В основе лежат объекты Subject и Observer. Субъект изменяется и уведомляет о своих изменениях зависимым от него Наблюдателям. Наблюдатели синхронизируют свои данных с Субъектом. Также это отношение называют издатель-подписчик. Субъект(издатель) рассылает уведомления своим наблюдателям(подписчикам), даже не зная о том, какие объекты ими являются. При этом количество подписчиков не ограничено.
Как это все будет выглядеть в Javascript?
Объявим издателей
Теперь подписчиков
Подпишем всех
Отправим подписчикам новости
Итак, теперь напишем конструктор для издателя. Внутри него хранятся подписчики.
Метод издателя, отправляющего своим подписчикам уведомление(расширение forEach для массивов можно взять с developer.mozilla.org)
И добавим в Function метод subscribe для добавления подписчика.
Ну вот. Паттерн готов.
Как это все использовать?
Я покажу как использовать данный паттерн для индикатора процесса длительного действия. Этим действием может быть обработка большого массива данных, загрузка файла на сервер, длительное передвижение какого-либо персонажа и, может когда-нибудь возможно будет во всех браузерах, обработка XHR до наступления readyState=4.
У меня будет передвигается панда по тропинке Сразу пример.
В конструкторе мы создали Издателя this.onGo=new Publisher(), а в методе сделали рассылку с текущим прогрессом that.onGo.deliver(progress).
Теперь осталось добавить наблюдателей для текущего состояния панды. Покажем прогрессбар и количество процентов пройденного пути. Очевидно, сделаем двух наблюдателя
И подпишем их на рассылку onGo
Теперь при движении панды изменяются и индикаторы.
В итоге мы получили три независимых объекта Bar, Status и Animal, которые можно использовать независимо друг от друга, а также возможность спокойно добавлять новые объекты, зависящие от состояния панды(издателя).
Похожего результата можно было бы достичь и с помощью jquery trigger/bind. Тогда бы вместо подписки, вешали бы bind. А в методе Animal.go добавляли trigger Пример с trigger/bind
Например, при изменении данных A, B, C диаграмма и таблица, отвечающие за представление, должны измениться. При этом неизвестно, сколько имеется представлений.

Паттерн наблюдатель описывает, как реализовать такое отношение. В основе лежат объекты Subject и Observer. Субъект изменяется и уведомляет о своих изменениях зависимым от него Наблюдателям. Наблюдатели синхронизируют свои данных с Субъектом. Также это отношение называют издатель-подписчик. Субъект(издатель) рассылает уведомления своим наблюдателям(подписчикам), даже не зная о том, какие объекты ими являются. При этом количество подписчиков не ограничено.
Как это все будет выглядеть в Javascript?
Объявим издателей
var Microsoft = new Publisher;
var Google = new Publisher;
var Apple = new Publisher;
* This source code was highlighted with Source Code Highlighter.
Теперь подписчиков
var Ann = function(from) {
console.log('Delivery from '+from+' to Ann');
};
var Vasya = function(from) {
console.log('Delivery from '+from+' to Vasya');
};
var Maria = function(from) {
console.log('Delivery from '+from+' to Maria ');
};
* This source code was highlighted with Source Code Highlighter.
Подпишем всех
Ann.subscribe(Microsoft).subscribe(Google).subscribe(Apple);
Vasya.subscribe(Google).subscribe(Apple);
Maria.subscribe(Microsoft);
* This source code was highlighted with Source Code Highlighter.
Отправим подписчикам новости
Microsoft.deliver('news 1').deliver('news 2');
Google.deliver('googlenews 1').deliver('googlenews 2');
* This source code was highlighted with Source Code Highlighter.
Итак, теперь напишем конструктор для издателя. Внутри него хранятся подписчики.
function Publisher() {
this.subscribers = [];
}
* This source code was highlighted with Source Code Highlighter.
Метод издателя, отправляющего своим подписчикам уведомление(расширение forEach для массивов можно взять с developer.mozilla.org)
Publisher.prototype.deliver = function(data) {
this.subscribers.forEach(
function(fn) {
fn(data);
}
);
return this;
};
* This source code was highlighted with Source Code Highlighter.
И добавим в Function метод subscribe для добавления подписчика.
Function.prototype.subscribe = function(publisher) {
publisher.subscribers.push(this);
return this;
};
* This source code was highlighted with Source Code Highlighter.
Ну вот. Паттерн готов.
Как это все использовать?
Я покажу как использовать данный паттерн для индикатора процесса длительного действия. Этим действием может быть обработка большого массива данных, загрузка файла на сервер, длительное передвижение какого-либо персонажа и, может когда-нибудь возможно будет во всех браузерах, обработка XHR до наступления readyState=4.
У меня будет передвигается панда по тропинке Сразу пример.
var Animal=function(id){
this.onGo=new Publisher();
this.id=id;
this.domElement=$('#'+id);
this.from=parseInt(this.domElement.css('left'));
}
Animal.prototype.go=function(to,duration){
var start = new Date().getTime();
var that=this;
setTimeout(function() {
var now = (new Date().getTime()) - start;
var progress = now / duration;
if(progress > 1) progress = 1;
var result = (to - that.from) * progress + that.from;
that.domElement.css('left', result+'px');
that.onGo.deliver(progress);
if (progress < 1)
setTimeout(arguments.callee, 10);
}, 10);
}
...
var Panda=new Animal('panda');
* This source code was highlighted with Source Code Highlighter.
В конструкторе мы создали Издателя this.onGo=new Publisher(), а в методе сделали рассылку с текущим прогрессом that.onGo.deliver(progress).
Теперь осталось добавить наблюдателей для текущего состояния панды. Покажем прогрессбар и количество процентов пройденного пути. Очевидно, сделаем двух наблюдателя
var Status=function(v){
var per=v*100;
if(per>100)v=100;
$("#status").html((per.toFixed(0))+"%")
}
var Bar=function(progress){
var w=(progress*596);
$("#progressbar").css('width',w+'px');
}
* This source code was highlighted with Source Code Highlighter.
И подпишем их на рассылку onGo
Bar.subscribe(Panda.onGo);
Status.subscribe(Panda.onGo);
* This source code was highlighted with Source Code Highlighter.
Теперь при движении панды изменяются и индикаторы.
В итоге мы получили три независимых объекта Bar, Status и Animal, которые можно использовать независимо друг от друга, а также возможность спокойно добавлять новые объекты, зависящие от состояния панды(издателя).
Похожего результата можно было бы достичь и с помощью jquery trigger/bind. Тогда бы вместо подписки, вешали бы bind. А в методе Animal.go добавляли trigger Пример с trigger/bind