Apakah Anda masih ingat bagaimana gangster bekerja sama dalam film polisi dan gangster? Ketika sebuah geng adalah pencurian, satu atau dua orang selalu mengambil angin di pintu. Jika ada gerakan, kaki tangan di dalam akan segera diberitahukan untuk segera mundur. Mungkin orang yang membiarkan berita itu tidak selalu mengetahui setiap kaki di dalamnya; Dan mungkin ada adik laki -laki baru yang tidak mengenal orang yang membiarkan berita. Tapi ini bukan apa -apa, itu tidak dapat mempengaruhi komunikasi mereka karena mereka memiliki kode yang telah disepakati.
Haha, hubungan antara usaha udara dan pencuri yang disebutkan di atas adalah contoh hidup dari pola pengamat dalam kenyataan.
Mode pengamat juga dikenal sebagai Mode Publish/Berlangganan. GOF mendefinisikan pola pengamat sebagai berikut: mendefinisikan ketergantungan satu-ke-banyak antara objek. Ketika keadaan suatu objek berubah, semua objek yang bergantung padanya diberitahu dan diperbarui secara otomatis.
Di sini saya pertama -tama akan berbicara tentang prinsip penting desain berorientasi objek - prinsip tanggung jawab tunggal. Oleh karena itu, setiap objek sistem harus fokus pada abstraksi diskrit dalam domain masalah. Oleh karena itu, idealnya, suatu objek hanya melakukan satu hal. Ini membawa banyak manfaat dalam pengembangan: ini memberikan reusability dan pemeliharaan, dan juga merupakan fondasi yang baik untuk refactoring.
Oleh karena itu, hampir semua pola desain didasarkan pada prinsip desain dasar ini. Saya pikir asal model pengamat harus dalam pemrosesan GUI dan data bisnis, karena sebagian besar contoh yang menjelaskan model pengamat sekarang adalah topik ini. Namun, penerapan mode pengamat sama sekali tidak terbatas pada aspek ini.
Nah, pemahaman definisi selalu membutuhkan contoh untuk dianalisis. Akun layanan WeChat cukup populer saat ini. Mari kita perkenalkan model pengamat kepada Anda dengan latar belakang akun layanan WeChat.
Lihatlah gambar:
Setiap pengguna memiliki 3 baris dalam gambar di atas, yang dihilangkan untuk memperjelas gambar.
Seperti yang ditunjukkan pada gambar di atas, nomor layanan adalah tema kami dan pengguna adalah pengamat. Sekarang kami mengklarifikasi fungsi -fungsi berikut:
1. Akun layanan adalah tema, dan bisnis mendorong pesan
2. Pengamat hanya perlu berlangganan topik, dan mereka akan dikirim segera setelah ada berita baru.
3. Berhenti Berlangganan Saat Anda Tidak Ingin Pesan Topik Ini
4. Selama akun layanan masih ada, seseorang akan berlangganan. Sekarang mari kita lihat diagram kelas dari pola pengamat:
Berikutnya adalah waktu kode, kami mensimulasikan akun layanan lotere 3D WeChat dan beberapa pelanggan.
Pertama, mulailah menulis tentang antarmuka topik kami dan antarmuka pengamat:
paket com.zhy.pattern.observer; / ** * Antarmuka topik, semua topik harus mengimplementasikan antarmuka ini * * @author zhy * */ subjek antarmuka publik {/ ** * Daftarkan pengamat * * @param Observer */ public void registeroBserver (pengamat pengamat); / ** * Hapus pengamat * * @param Observer */ public void RemestoBserver (Observer Observer); / *** beri tahu semua pengamat*/ public void notifyoBserver (); } paket com.zhy.pattern.observer; / *** @Author Zhy Semua pengamat perlu mengimplementasikan antarmuka ini*/ Public Interface Observer {public void update (string msg); }Kelas Implementasi Nomor Layanan 3D Berikutnya:
paket com.zhy.pattern.observer; impor java.util.arraylist; impor java.util.list; Public Class ObjectFor3D mengimplementasikan Subjek {Private List <Sobserver> Observer = ArrayList baru <Ibserver> (); / *** Nomor Lotere 3D*/ Private String Msg; @Override public void registeroBserver (pengamat pengamat) {pengamat.add (pengamat); } @Override public void RemestoBserver (Observer Observer) {int index = Observer.IndexOf (Observer); if (index> = 0) {Observer.Remove (index); }} @Override public void notifyoBserver () {for (Observer Observer: Observer) {Observer.update (msg); }} / ** * Pesan Pembaruan Topik * * @param msg * / public void setMsg (string msg) {this.msg = msg; notifyoBserver (); }}Simulasikan dua pengguna:
paket com.zhy.pattern.observer; Public Class Observer1 mengimplementasikan pengamat {subjek subjek pribadi; pengamat publik1 (subjek subjek) {this.subject = subjek; subjek.RegisteroBserver (ini); } @Override public void update (string msg) {System.out.println ("Observer1 Mendapat nomor 3D ->" + msg + ", saya ingin menuliskannya."); }} paket com.zhy.pattern.observer; Public Class Observer2 mengimplementasikan pengamat {subjek subjek pribadi; pengamat publik2 (subjek subjek) {this.subject = subjek; subjek.RegisteroBserver (ini); } @Override public void update (String msg) {System.out.println ("Observer2 Mendapat nomor 3D ->" + msg + "Saya ingin memberi tahu teman sekamar saya."); }} Dapat dilihat bahwa semua pengguna yang berlangganan pesan disimpan di akun layanan, dan semua pengguna diberi tahu ketika ada pesan baru di akun layanan. Seluruh arsitektur adalah kopling longgar, dan implementasi tema tidak tergantung pada pengguna. Ketika pengguna baru ditambahkan, kode tema tidak perlu diubah; bagaimana pengguna memproses data yang diperoleh tidak ada hubungannya dengan tema;
Akhirnya, lihat kode uji:
paket com.zhy.pattern.observer.test; impor com.zhy.pattern.observer.objectfor3d; impor com.zhy.pattern.observer.observer; impor com.zhy.pattern.observer.observer1; impor com.zhy.pattern.observer.observer2; impor com.zhy.pattern.observer.subject; tes kelas publik {public static void main (string [] args) {// simulasikan nomor layanan 3D objectFor3D subjekfor3d = new ObjectFor3D (); // Customer1 Observer Observer1 = Observer baru (SubjectFor3D); Observer Observer2 = New Observer2 (SubjectFor3D); SubjectFor3D.SetMSG ("Nomor 3D 20140420 adalah: 127"); SubjectFor3D.SetMSG ("Nomor 3D 20140421 adalah: 333"); }}Hasil output:
Observer1 Mendapat Nomor 3D -> Nomor 3D 20140420 adalah: 127, saya ingin menuliskannya. Observer2 Mendapat Nomor 3D -> Nomor 3D 20140420 adalah: 127 Saya ingin memberi tahu teman sekamar saya. Observer1 Mendapat Nomor 3D -> Nomor 3D 20140421 adalah: 333, saya ingin menuliskannya. Observer2 Mendapat Nomor 3D -> Nomor 3D 20140421 adalah: 333 Saya ingin memberi tahu teman sekamar saya.
Ada banyak tempat di JDK atau andorid yang mengimplementasikan mode pengamat, seperti xxxview.addxxxlistenter. Tentu saja, xxxview.setonxxxlistener tidak selalu merupakan mode pengamat, karena mode pengamat adalah hubungan satu-ke-banyak. Untuk SetxxxListener, ini adalah hubungan 1-ke-1, dan itu harus disebut panggilan balik.
Selamat atas Mode Pengamat. Mode pengamat di atas memungkinkan kita untuk menuliskannya dari awal. Tentu saja, Java telah membantu kami menerapkan mode pengamat, dengan bantuan java.util.observable dan java.util.observer.
Di bawah ini kami menggunakan kelas bawaan Java untuk mengimplementasikan pola pengamat:
Pertama -tama, ada tema nomor layanan lotere 3D:
paket com.zhy.pattern.observer.java; impor java.util.observable; Public Class SubjectFor3D memperluas {private string msg; Public String getMSG () {return msg; } / ** * Pesan Pembaruan Topik * * @param msg * / public void setMsg (string msg) {this.msg = msg; setChanged (); notifyoBserver (); }}Berikut ini adalah tema nomor layanan bola warna ganda:
paket com.zhy.pattern.observer.java; impor java.util.observable; Subject Class PublicForsSQ memperluas {private string msg; Public String getMSG () {return msg; } / ** * Pesan Pembaruan Topik * * @param msg * / public void setMsg (string msg) {this.msg = msg; setChanged (); notifyoBserver (); }}Akhirnya, pengguna kami:
paket com.zhy.pattern.observer.java; impor java.util.observable; impor java.util.observer; Public Class Observer1 mengimplementasikan Observer {public void registerubject (Observable Observable) {Observable.addoBserver (ini); } @Override public void update (Observable o, objek arg) {if (o instanceof SubjectFor3d) {SubjectFor3D SubjectFor3d = (SubjectFor3D) o; System.out.println ("MSG SubjectFor3D ->" + SubjectFor3D.GetMSg ()); } if (o instanceof SubjectForSsq) {SubjectForsSQ SubjectForSsq = (SubjectForsSQ) o; System.out.println ("MSG SubjectForsSQ ->" + SubjectForsSQ.GetMSg ()); }}}Lihatlah kode uji:
paket com.zhy.pattern.observer.java; tes kelas publik {public static void main (string [] args) {SubjectFor3D SubjectFor3d = new SubjectFor3D (); SubjectForsSQ SubjectForSSQ = new SubjectForsSQ (); Observer1 Observer1 = New Observer1 (); Observer1.registersubject (subjekfor3d); Observer1.Registersubject (SubjectForsSQ); SubjectFor3d.setMSg ("Hello 3d'nums: 110"); Subjectforssq.setMSG ("Ssq'nums: 12,13,31,5,4,3 15"); }}Hasil tes:
MSG Subjekfor3D -> Hello 3d'nums: 110 SubjectForsSQ's MSG -> SSQ'nums: 12,13,31,5,4,3 15
Dapat dilihat bahwa menggunakan kelas bawaan Java untuk mengimplementasikan pola pengamat, kode ini sangat ringkas. Ngomong -ngomong, addoBserver, RemestoBServer, NotifyObserver telah diimplementasikan untuk kita. Yang bisa kita lihat bahwa dapat diamati adalah kelas, bukan antarmuka. Pada dasarnya, buku ini memiliki sikap negatif terhadap desain Java. Rasanya pola pengamat bawaan Java melanggar prinsip pemrograman yang berorientasi antarmuka. Namun, jika Anda memikirkannya, Anda memang menulis pola pengamat di sini (implementasi kami sendiri). Gagasan antarmuka sangat bagus, tetapi jika Anda terus menambahkan banyak topik sekarang, DDOBServer, RemoveObserver, NotifyOBServer untuk setiap topik pada dasarnya sama. Antarmuka tidak dapat menerapkan penggunaan kembali kode, dan tidak ada cara untuk menggunakan mode gabungan untuk mencapai penggunaan kembali dari ketiga metode ini, jadi saya pikir masuk akal untuk mengimplementasikan ketiga metode ini di kelas di sini.