
Javascript. Простий Observer.
Завдання - зв'язати 2 абсолютно будь-які об'єкти. Не можна змінювати початковий код об'єктів.
Описане нижче розраховане на самостійність читача і бажання розібратися в реалізації.
Приклад (утрований).
Є 2 об'єкти в будинку:
<div id=""a1"" onclick=""alert(123)""></div>
<div id=""a2""></div>
І 1 яваскриптовий:
Core = function() {
this.some = function(a,b,c,d,e,f,g) {
var a1 = $('a1').innerHTML
var a2 = a+''+b+''+c+''+d+''+e+''+f+''+g
$('a1').innerHTML = a1 + a2
}
this.another = function() {
var a = $('a1').innerHTML
var a2 = 'some_text_more'
$('a1').innerHTML = a + a2
}
this.another2 = function() {
var a = $('a2').innerHTML
var a2 = 'yahoo'
$('a2').innerHTML = a + a2
}
}
var Core = new Core()
Потрібно: відреагувати на a1.onclick викликом Core.another2
Реалізація:
var n = Observer.Attach($('a1'), 'onclick', Core, 'another')
Прибираємо Observer:
Observer.Dettach($('a1'), n)
Observer.
Реалізація побудована на клонуванні методу відстежуваного об'єкта.
Observer.Attach клонує метод, створюючи новий з унікальним ім'ям.
Відстежуваному методу присвоюється нова дія, що містить виклик клону і виклик необхідної функції (obj2.call_back)
Черговість виклику контролюємо параметром before методу Observer.Attach.
Observer = function() {}
Observer.prototype = {
List: {},
Attach: function(obj, method, obj2, call_back, before) {
var new_method = this. CloneOldMethod(obj, method)
eval('obj.'+method+' = '+this.NewDefaultMethod('obj2', call_back, new_method, before))
return new_method
},
Dettach: function(obj, observed_method) {
eval('var m = this. List.'+observed_method)
eval('obj.'+m.method+' = m.realization')
eval('delete(obj.'+observed_method+')')
eval('delete(this.List.'+observed_method+')')
},
NewDefaultMethod: function(obj_name, call_back, new_method, before) {
var m_old = 'this.'+new_method+'(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6])'
var m_new = obj_name+'.'+call_back+'()'
var cmd = ''
cmd += 'function() {'
before === true ? cmd += m_new +';'+ m_old : cmd += m_old +';'+ m_new
cmd += '}'
return cmd
},
CloneOldMethod: function(obj, method) {
var new_method = 'a'+this.giveUnique()
eval('obj.'+new_method+' = obj.'+method)
eval('this.List.'+new_method+' = {object: obj, \'method\': method, realization:obj.'+method+'}')
return new_method
},
giveUnique: function () {
return (new Date()).getTime()
}
}
Observer = new Observer()