memperkenalkan
Mode pengamat juga disebut publikasi/berlangganan. Ini mendefinisikan hubungan satu-ke-banyak, memungkinkan beberapa objek pengamat untuk mendengarkan objek topik pada saat yang sama. Ketika keadaan objek topik ini berubah, semua objek pengamat akan diberitahu, sehingga mereka dapat secara otomatis memperbarui diri mereka sendiri.
Manfaat Menggunakan Mode Pengamat:
1. Mendukung komunikasi siaran sederhana dan secara otomatis memberi tahu semua objek yang berlangganan.
2. Setelah halaman dimuat, objek target dapat dengan mudah memiliki korelasi dinamis dengan pengamat, yang meningkatkan fleksibilitas.
3. Hubungan kopling abstrak antara objek target dan pengamat dapat diperluas dan digunakan kembali secara terpisah.
Teks (versi 1)
Implementasi pola pengamat di JS dicapai melalui panggilan balik. Pertama -tama mari kita tentukan objek pubsub, yang berisi 3 metode: berlangganan, berhenti berlangganan, dan publikasikan.
Salinan kode adalah sebagai berikut:
var pubsub = {};
(function (q) {
var topik = {}, // array disimpan oleh fungsi callback
subuid = -1;
// Metode Publikasikan
q.publish = function (topic, args) {
if (! Topics [topic]) {
mengembalikan false;
}
setTimeout (function () {
Var Subscribers = Topik [Topik],
len = pelanggan? pelanggan.length: 0;
while (len--) {
pelanggan [len] .func (topik, args);
}
}, 0);
Kembali Benar;
};
// Metode Berlangganan
q.subscribe = function (topic, func) {
if (! Topics [topic]) {
topik [topik] = [];
}
var token = (++ subuid) .toString ();
Topik [topik] .push ({
Token: Token,
Func: Func
});
Token kembali;
};
// Metode berhenti berlangganan
q.unsubscribe = function (token) {
untuk (var m dalam topik) {
if (topik [m]) {
untuk (var i = 0, j = topik [m] .length; i <j; i ++) {
if (topik [m] [i] .token === token) {
topik [m] .splice (i, 1);
Token kembali;
}
}
}
}
mengembalikan false;
};
} (pubsub));
Cara menggunakannya adalah sebagai berikut:
Salinan kode adalah sebagai berikut:
// datang, berlangganan satu
pubsub.subscribe ('example1', function (topik, data) {
console.log (topik + ":" + data);
});
// Pemberitahuan rilis
pubsub.publish ('example1', 'Hello World!');
pubsub.publish ('example1', ['test', 'a', 'b', 'c']);
pubsub.publish ('example1', [{'color': 'blue'}, {'text': 'hello'}]);
Bagaimana dengan itu? Bukankah itu bagus untuk digunakan? Tetapi ada masalah dengan metode ini, yaitu, tidak ada cara untuk berhenti berlangganan. Jika Anda ingin berhenti berlangganan, Anda harus menentukan nama berhenti berlangganan, jadi mari kita pergi ke versi lain:
Salinan kode adalah sebagai berikut:
// Tetapkan langganan ke variabel untuk berhenti berlangganan
var testsubscription = pubsub.subscribe ('example1', function (topik, data) {
console.log (topik + ":" + data);
});
// Pemberitahuan rilis
pubsub.publish ('example1', 'Hello World!');
pubsub.publish ('example1', ['test', 'a', 'b', 'c']);
pubsub.publish ('example1', [{'color': 'blue'}, {'text': 'hello'}]);
// tidak ditangani
setTimeout (function () {
pubsub.unsubscribe (TestSubscription);
}, 0);
// Publikasikan lagi untuk memverifikasi apakah informasi tersebut masih bisa menjadi output
pubsub.publish ('Contoh1', 'Halo lagi! (Ini akan gagal)');
Versi 2
Kami juga dapat menggunakan karakteristik prototipe untuk mengimplementasikan pola pengamat, kodenya adalah sebagai berikut:
Salinan kode adalah sebagai berikut:
fungsi pengamat () {
this.fns = [];
}
Observer.prototype = {
Berlangganan: function (fn) {
this.fns.push (fn);
},
berhenti berlangganan: function (fn) {
this.fns = this.fns.filter (
function (el) {
if (el! == fn) {
mengembalikan el;
}
}
);
},
UPDATE: function (o, thisobj) {
var scope = thisobj || jendela;
this.fns.foreach (
function (el) {
el.call (lingkup, o);
}
);
}
};
//tes
var o = pengamat baru;
var f1 = fungsi (data) {
console.log ('Robbin:' + data + ', bekerja dengan cepat!');
};
var f2 = fungsi (data) {
console.log ('randall:' + data + ', temukan dia untuk mendapatkan gaji tambahan!');
};
o.subscribe (f1);
o.subscribe (f2);
o.update ("Tom sudah kembali!")
// berhenti berlangganan F1
o.unsubscribe (f1);
// Periksa lagi
o.update ("Tom sudah kembali!");
Jika fungsi filter atau foreach tidak ditemukan, itu mungkin karena browser Anda tidak cukup baru dan tidak mendukung fungsi standar baru untuk saat ini. Anda dapat mendefinisikannya sendiri dengan cara berikut:
Salinan kode adalah sebagai berikut:
if (! array.prototype.foreach) {
Array.prototype.foreach = function (fn, thisobj) {
var scope = thisobj || jendela;
untuk (var i = 0, j = this.length; i <j; ++ i) {
fn.call (lingkup, ini [i], i, ini);
}
};
}
if (! array.prototype.filter) {
Array.prototype.filter = function (fn, thisobj) {
var scope = thisobj || jendela;
var a = [];
untuk (var i = 0, j = this.length; i <j; ++ i) {
if (! fn.call (lingkup, ini [i], i, this)) {
melanjutkan;
}
A.Push (ini [i]);
}
mengembalikan a;
};
}
Versi 3
Jika Anda ingin beberapa objek memiliki fungsi langganan penerbitan pengamat, kami dapat mendefinisikan fungsi umum dan kemudian menerapkan fungsi fungsi ke objek yang membutuhkan fungsi pengamat. Kodenya adalah sebagai berikut:
Salinan kode adalah sebagai berikut:
// Kode Universal
var pengamat = {
// Berlangganan
AddSubscriber: function (callback) {
this.subscribers [this.subscribers.length] = callback;
},
// tidak ditangani
RemoveSubscriber: function (callback) {
untuk (var i = 0; i <this.subscribers.length; i ++) {
if (this.subscribers [i] === callback) {
hapus (this.subscribers [i]);
}
}
},
//melepaskan
Publikasikan: function (apa) {
untuk (var i = 0; i <this.subscribers.length; i ++) {
if (typeof this.subscribers [i] === 'function') {
this.subscribers [i] (apa);
}
}
},
// buat objek o memiliki fungsi pengamat
buat: function (o) {
untuk (var i di ini) {
o [i] = ini [i];
o.subscribers = [];
}
}
};
Kemudian berlangganan 2 blogger dan pengguna objek, gunakan metode pengamat.
Salinan kode adalah sebagai berikut:
var blogger = {
Rekomendasikan: function (id) {
var msg = 'dudu yang disarankan posting:' + id;
this.publish (msg);
}
};
var user = {
vote: function (id) {
var msg = 'seseorang memilih! id =' + id;
this.publish (msg);
}
};
Observer.Make (Blogger);
Observer.make (pengguna);
Metode penggunaan relatif sederhana. Berlangganan fungsi panggilan balik yang berbeda sehingga Anda dapat mendaftar dengan objek pengamat yang berbeda (atau beberapa objek pengamat dapat didaftarkan pada saat yang sama):
Salinan kode adalah sebagai berikut:
var tom = {
baca: function (apa) {
Console.log ('Tom melihat pesan berikut:' + apa)
}
};
var mm = {
Tampilkan: function (apa) {
console.log ('mm melihat pesan berikut:' + apa)
}
};
// Berlangganan
blogger.addsubscriber (tom.read);
Blogger.addsubscriber (mm.show);
Blogger.Recmend (123); // Hubungi Publish
// tidak ditangani
blogger.removesubscriber (mm.show);
Blogger.Recmend (456); // Hubungi Publish
// Berlangganan ke objek lain
user.addsubscriber (mm.show);
user.vote (789); // Hubungi Publish
versi jQuery
Menurut fungsi on/off yang ditambahkan dalam jQuery versi 1.7, kita juga dapat mendefinisikan pengamat versi jQuery:
Salinan kode adalah sebagai berikut:
(function ($) {
var o = $ ({});
$ .subscribe = function () {
o.on.Apply (o, argumen);
};
$ .unsubscribe = function () {
o.off.Apply (o, argumen);
};
$ .publish = function () {
o.trigger.Apply (o, argumen);
};
} (jQuery));
Metode panggilan lebih sederhana dari tiga versi di atas:
Salinan kode adalah sebagai berikut:
// fungsi panggilan balik
fungsi pegangan (e, a, b, c) {
// `e` adalah objek acara, tidak diperlukan perhatian
console.log (a + b + c);
};
// Berlangganan
$ .subscribe ("/beberapa/topik", pegangan);
//melepaskan
$ .publish ("/beberapa/topik", ["a", "b", "c"]); // output ABC
$ .unsubscribe ("/beberapa/topik", pegangan); // berhenti berlangganan
// Berlangganan
$ .subscribe ("/beberapa/topik", fungsi (e, a, b, c) {
console.log (a + b + c);
});
$ .publish ("/beberapa/topik", ["a", "b", "c"]); // output ABC
// berhenti berlangganan (berhenti berlangganan menggunakan/beberapa nama topik, bukan fungsi callback, yang berbeda dari contoh versi 1
$ .unsubscribe ("/beberapa/topik");
Dapat dilihat bahwa berlangganan dan berhenti berlangganan menggunakan nama string, bukan nama fungsi panggilan balik, jadi bahkan jika fungsi anonim yang masuk dilewati, kita dapat berhenti berlangganan.
Meringkaskan
Penggunaan pengamat adalah: Ketika suatu objek berubah untuk mengubah objek lain secara bersamaan dan tidak tahu berapa banyak objek yang perlu diubah, ia harus mempertimbangkan untuk menggunakan mode pengamat.
Secara keseluruhan, apa yang dilakukan oleh pola pengamat adalah decouple, membuat kedua sisi kopling bergantung pada abstraksi daripada beton. Ini memungkinkan bahwa perubahan satu sama lain tidak akan mempengaruhi perubahan di sisi lain.