Mode pengamat, juga dikenal sebagai mode publikasi/berlangganan, diusulkan oleh kelompok empat orang (GOF, yaitu Erich Gamma, Richard Helm, Ralph Johnson dan John Vlissides) dalam "Pola Desain: Dasar-dasar Perangkat Lunak Berorientasi Objek yang Dapat Digunakan kembali" (lihat halaman 293-313 dalam detail). Meskipun pola ini memiliki sejarah yang cukup besar, masih banyak berlaku untuk berbagai skenario dan bahkan telah menjadi bagian integral dari Perpustakaan Java standar. Meskipun sudah ada banyak artikel tentang pola pengamat, mereka semua fokus pada implementasi di Java, tetapi mengabaikan berbagai masalah yang dihadapi oleh pengembang saat menggunakan pola pengamat di Java.
Tujuan asli menulis artikel ini adalah untuk mengisi kesenjangan ini: Artikel ini terutama memperkenalkan implementasi pola pengamat dengan menggunakan arsitektur Java8, dan lebih lanjut mengeksplorasi masalah kompleks tentang pola klasik atas dasar ini, termasuk kelas internal anonim, ekspresi Lambda, keselamatan utas, dan implementasi pengamat waktu-konsumen yang tidak sepele. Meskipun konten artikel ini tidak komprehensif, banyak masalah kompleks yang terlibat dalam model ini tidak dapat dijelaskan hanya dalam satu artikel. Tetapi setelah membaca artikel ini, pembaca dapat memahami apa pola pengamat, universalitasnya di Java, dan bagaimana menangani beberapa masalah umum ketika menerapkan pola pengamat di Java.
Mode pengamat
Menurut definisi klasik yang diusulkan oleh GOF, tema pola pengamat adalah:
Mendefinisikan ketergantungan satu-ke-banyak antara objek. Ketika keadaan suatu objek berubah, semua objek yang bergantung padanya diberitahu dan diperbarui secara otomatis.
Apa artinya? Dalam banyak aplikasi perangkat lunak, status antar objek saling bergantung. Misalnya, jika aplikasi berfokus pada pemrosesan data numerik, data ini dapat ditampilkan melalui tabel atau bagan antarmuka pengguna grafis (GUI) atau digunakan pada saat yang sama, yaitu, ketika data yang mendasarinya diperbarui, komponen GUI yang sesuai juga harus diperbarui. Kunci masalah ini adalah bagaimana memperbarui data yang mendasari ketika komponen GUI diperbarui, dan pada saat yang sama meminimalkan kopling antara komponen GUI dan data yang mendasarinya.
Solusi yang sederhana dan tidak dapat ditentukan adalah merujuk pada tabel dan komponen GUI gambar dari objek yang mengelola data yang mendasarinya, sehingga objek dapat memberi tahu komponen GUI ketika data yang mendasarinya berubah. Jelas, solusi sederhana ini dengan cepat menunjukkan kekurangannya untuk aplikasi kompleks yang menangani lebih banyak komponen GUI. Misalnya, ada 20 komponen GUI yang semuanya bergantung pada data yang mendasari, sehingga objek yang mengelola data yang mendasari perlu mempertahankan referensi ke 20 komponen ini. Dengan jumlah objek yang bergantung pada data terkait meningkat, tingkat kopling antara manajemen data dan objek menjadi sulit dikendalikan.
Solusi lain yang lebih baik adalah untuk mengizinkan objek untuk mendaftar untuk mendapatkan izin untuk memperbarui data yang menarik, yang akan diberitahukan oleh manajer data ketika data berubah. Dalam istilah awam, biarkan objek data yang menarik memberi tahu manajer: "Harap beri tahu saya ketika data berubah." Selain itu, objek -objek ini tidak hanya dapat mendaftar untuk mendapatkan pemberitahuan pembaruan, tetapi juga membatalkan pendaftaran untuk memastikan bahwa manajer data tidak lagi memberi tahu objek ketika data berubah. Dalam definisi asli GOF, objek yang terdaftar untuk mendapatkan pembaruan disebut "pengamat", manajer data yang sesuai disebut "subjek", data yang diminati pengamat disebut "status target", proses pendaftaran disebut "Tambah" dan proses pengamatan yang membatalkan disebut "melepaskan". Seperti disebutkan di atas, mode pengamat juga disebut Mode Penerbitan-Subjikan. Dapat dipahami bahwa pelanggan berlangganan pengamat tentang target. Ketika status target diperbarui, target menerbitkan pembaruan ini kepada pelanggan (pola desain ini diperluas ke arsitektur umum, yang disebut arsitektur berlangganan publikasi). Konsep -konsep ini dapat diwakili oleh diagram kelas berikut:
ConcereteObserver menggunakannya untuk menerima perubahan status pembaruan dan memberikan referensi ke ConcereteSubject ke konstruktornya. Ini memberikan referensi ke subjek tertentu untuk pengamat tertentu, dari mana pembaruan dapat diperoleh ketika keadaan berubah. Sederhananya, pengamat spesifik akan diberitahu untuk memperbarui topik, dan pada saat yang sama menggunakan referensi dalam konstruktornya untuk mendapatkan keadaan topik tertentu, dan akhirnya menyimpan objek negara pencarian ini di bawah properti Observerstate dari pengamat tertentu. Proses ini ditampilkan dalam diagram urutan berikut:
Profesionalisasi model klasik
Meskipun model pengamat bersifat universal, ada banyak model khusus, yang paling umum adalah dua berikut:
Memberikan parameter ke objek negara, diteruskan ke metode pembaruan yang dipanggil oleh pengamat. Dalam mode klasik, ketika pengamat diberitahu bahwa keadaan subjek telah berubah, keadaan yang diperbarui akan diperoleh langsung dari subjek. Ini mengharuskan pengamat untuk menyimpan referensi objek ke keadaan yang diambil. Ini membentuk referensi melingkar, referensi titik -titik concretesubject ke daftar pengamatnya, dan referensi poin ConcreteObserver ke Concretesubject yang dapat memperoleh keadaan subjek. Selain mendapatkan status yang diperbarui, tidak ada hubungan antara pengamat dan subjek yang didengarkannya. Pengamat peduli dengan objek negara, bukan subjek itu sendiri. Dengan kata lain, dalam banyak kasus, ConcreteObserver dan Concretesubject secara paksa dihubungkan bersama. Sebaliknya, ketika Concretesubject memanggil fungsi pembaruan, objek negara diteruskan ke ConcreteObserver, dan keduanya tidak perlu dikaitkan. Hubungan antara concreteobserver dan objek negara mengurangi tingkat ketergantungan antara pengamat dan negara (lihat artikel Martin Fowler untuk lebih banyak perbedaan dalam hubungan dan ketergantungan).
Gabungkan kelas abstrak subjek dan concretesubject ke dalam kelas singlesubject. Dalam kebanyakan kasus, penggunaan kelas abstrak dalam subjek tidak meningkatkan fleksibilitas dan skalabilitas program, sehingga menggabungkan kelas abstrak dan kelas beton ini menyederhanakan desain.
Setelah dua model khusus ini digabungkan, diagram kelas yang disederhanakan adalah sebagai berikut:
Dalam model khusus ini, struktur kelas statis sangat disederhanakan dan interaksi antar kelas juga disederhanakan. Diagram urutan saat ini adalah sebagai berikut:
Fitur lain dari mode spesialisasi adalah penghapusan pengamat variabel anggota dari ConcreteObserver. Kadang -kadang pengamat spesifik tidak perlu menyimpan keadaan terbaru dari subjek, tetapi hanya perlu memantau status subjek ketika status diperbarui. Misalnya, jika pengamat memperbarui nilai variabel anggota ke output standar, ia dapat menghapus Observerstate, yang menghapus hubungan antara konkreteobserver dan kelas negara.
Aturan penamaan yang lebih umum
Model klasik dan bahkan model profesional yang disebutkan di atas menggunakan istilah -istilah seperti lampirkan, melepaskan dan pengamat, sementara banyak implementasi Java menggunakan kamus yang berbeda, termasuk register, unregister, pendengar, dll. Perlu disebutkan bahwa negara adalah istilah umum untuk semua objek yang diperlukan pendengar untuk memantau perubahan. Nama spesifik objek negara tergantung pada skenario yang digunakan dalam mode pengamat. Misalnya, dalam mode pengamat dalam adegan di mana pendengar mendengarkan kejadian peristiwa, pendengar terdaftar akan menerima pemberitahuan ketika peristiwa terjadi. Objek status saat ini adalah peristiwa, yaitu, apakah peristiwa telah terjadi.
Dalam aplikasi yang sebenarnya, penamaan target jarang termasuk subjek. Misalnya, buat aplikasi tentang kebun binatang, daftarkan banyak pendengar untuk mengamati kelas kebun binatang, dan terima pemberitahuan ketika hewan baru memasuki kebun binatang. Tujuan dalam kasus ini adalah kelas kebun binatang. Untuk menjaga terminologi konsisten dengan domain masalah yang diberikan, istilah "subjek" tidak akan digunakan, yang berarti bahwa kelas kebun binatang tidak akan dinamai zoosubject.
Penamaan pendengar umumnya diikuti oleh akhiran pendengar. Misalnya, pendengar yang disebutkan di atas untuk memantau hewan baru akan dinamai AnimalAddedListener. Demikian pula, penamaan fungsi seperti register, lepas dan beri tahu sering dimusnahkan dengan nama pendengar yang sesuai. Misalnya, fungsi register, lepaskan, dan beri tahu tentang animaladdedlistener akan dinamai registeranimaladdedlistener, unregisteranimaladdedlistener dan notifyanimaladdedlistener. Perlu dicatat bahwa nama fungsi notify digunakan, karena fungsi notify menangani banyak pendengar daripada satu pendengar.
Metode penamaan ini akan tampak panjang, dan biasanya subjek akan mendaftarkan beberapa jenis pendengar. Misalnya, dalam contoh kebun binatang yang disebutkan di atas, di kebun binatang, selain mendaftarkan pendengar baru untuk memantau hewan, ia juga perlu mendaftarkan pendengar hewan untuk mengurangi pendengar. Pada saat ini, akan ada dua fungsi register: (Registeranimaladdedlistener dan registeranimalremovedlistener. Dengan cara ini, jenis pendengar digunakan sebagai kualifikasi untuk menunjukkan jenis pengamat. Solusi lain adalah membuat fungsi yang lebih baik dan kelebihan beban, tetapi solusi 1 dapat lebih mudah mengetahui pendengar yang lebih rendah.
Sintaks idiomatik lainnya adalah untuk digunakan pada awalan alih -alih pembaruan, misalnya, fungsi pembaruan bernama Onanimaladded alih -alih UpdateAnimaladded. Situasi ini lebih umum ketika pendengar mendapat pemberitahuan untuk urutan, seperti menambahkan hewan ke daftar, tetapi jarang digunakan untuk memperbarui data yang terpisah, seperti nama hewan.
Selanjutnya, artikel ini akan menggunakan aturan simbolik Java. Meskipun aturan simbolis tidak akan mengubah desain nyata dan implementasi sistem, ini adalah prinsip pengembangan yang penting untuk menggunakan istilah yang akrab dengan pengembang lain, jadi Anda harus terbiasa dengan aturan simbolik pola pengamat di Java yang dijelaskan di atas. Konsep di atas akan dijelaskan di bawah ini menggunakan contoh sederhana di lingkungan Java 8.
Contoh sederhana
Ini juga merupakan contoh kebun binatang yang disebutkan di atas. Menggunakan antarmuka API Java8 untuk mengimplementasikan sistem sederhana, menjelaskan prinsip -prinsip dasar dari pola pengamat. Masalahnya digambarkan sebagai:
Buat kebun binatang sistem, memungkinkan pengguna untuk mendengarkan dan membatalkan keadaan menambahkan hewan objek baru, dan membuat pendengar tertentu, bertanggung jawab untuk mengeluarkan nama hewan baru.
Menurut pembelajaran sebelumnya dari pola pengamat, kita tahu bahwa untuk mengimplementasikan aplikasi semacam itu, kita perlu membuat 4 kelas, khususnya:
Kelas Zoo: yaitu tema dalam pola, yang bertanggung jawab untuk menyimpan semua hewan di kebun binatang dan memberi tahu semua pendengar terdaftar ketika hewan baru bergabung.
Kelas Hewan: mewakili objek hewan.
Kelas AnimalAddedListener: Artinya, Antarmuka Pengamat.
PrintNeanimaladdedListener: Kelas pengamat spesifik bertanggung jawab untuk mengeluarkan nama hewan yang baru ditambahkan.
Pertama, kami membuat kelas hewan, yang merupakan objek Java sederhana yang berisi variabel anggota, konstruktor, getters dan metode setter. Kodenya adalah sebagai berikut:
Public Class Animal {Private String Name; Public Animal (Name String) {this.name = name;} public String getName () {return this.name;} public void setName (name string) {this.name = name;}}Gunakan kelas ini untuk mewakili objek hewan, dan kemudian Anda dapat membuat antarmuka animalAddDistener:
antarmuka publik animaladdedlistener {public void onanimaladded (hewan hewan);}Dua kelas pertama sangat sederhana, jadi saya tidak akan memperkenalkannya secara detail. Selanjutnya, buat kelas kebun binatang:
Kebun Binatang Kelas Publik {Daftar Pribadi <En Animal> Hewan = ArrayList baru <> (); Daftar Pribadi <En AnimalAddedListener> pendengar = Daftar Array baru <> (); public void addanimal (hewan hewan) {// Tambahkan hewan ke daftar hewan ini. RegisteranimaladdedListener (AnimalAddedListener listener) {// Tambahkan pendengar ke daftar pendengar terdaftar ini.listeners.add (pendengar);} void publik unregisteranimaladdedDistener (linanur animaladdistener) {// hapus pendengar dari daftar pendengar yang terdaftar. NotifyAnimaladdedListeners (hewan hewan) {// beri tahu masing -masing pendengar dalam daftar pendengar pendengar terdaftar ini.listeners.foreach (pendengar -> listener.updateanimaladded (hewan));}}Analogi ini kompleks dari dua sebelumnya. Ini berisi dua daftar, satu digunakan untuk menyimpan semua hewan di kebun binatang dan yang lainnya digunakan untuk menyimpan semua pendengar. Mengingat bahwa benda -benda yang disimpan dalam koleksi hewan dan pendengar sederhana, artikel ini memilih arraylist untuk penyimpanan. Struktur data spesifik dari pendengar yang disimpan tergantung pada masalahnya. Misalnya, untuk masalah kebun binatang di sini, jika pendengar memiliki prioritas, Anda harus memilih struktur data lain, atau menulis ulang algoritma register pendengar.
Implementasi pendaftaran dan penghapusan adalah metode delegasi sederhana: Setiap pendengar ditambahkan atau dihapus dari daftar mendengarkan pendengar sebagai parameter. Implementasi fungsi notify sedikit dimatikan dari format standar pola pengamat. Ini termasuk parameter input: hewan yang baru ditambahkan, sehingga fungsi notify dapat meneruskan referensi hewan yang baru ditambahkan ke pendengar. Gunakan fungsi foreach dari API Streams untuk melintasi pendengar dan menjalankan fungsi Theonanimaladded pada setiap pendengar.
Dalam fungsi addanimal, objek hewan yang baru ditambahkan dan pendengar ditambahkan ke daftar yang sesuai. Jika kompleksitas proses pemberitahuan tidak diperhitungkan, logika ini harus dimasukkan dalam metode panggilan yang nyaman. Anda hanya perlu meneruskan referensi ke objek hewan yang baru ditambahkan. Inilah sebabnya mengapa implementasi logis dari pendengar pemberitahuan dienkapsulasi dalam fungsi notifyanimaladdedlisteners, yang juga disebutkan dalam implementasi addanimal.
Selain masalah logis dari fungsi -fungsi notify, perlu untuk menekankan masalah kontroversial tentang visibilitas fungsi -fungsi notify. Dalam model pengamat klasik, seperti yang dikatakan GOF pada halaman 301 dari pola desain buku, fungsi notify adalah publik, tetapi meskipun digunakan dalam pola klasik, ini tidak berarti bahwa itu harus publik. Pemilihan visibilitas harus didasarkan pada aplikasi. Misalnya, dalam contoh kebun binatang artikel ini, fungsi notify adalah jenis yang dilindungi dan tidak mengharuskan setiap objek untuk memulai pemberitahuan pengamat terdaftar. Ini hanya perlu memastikan bahwa objek dapat mewarisi fungsi dari kelas induk. Tentu saja, ini bukan masalahnya. Penting untuk mengetahui kelas mana yang dapat mengaktifkan fungsi notify, dan kemudian menentukan visibilitas fungsi.
Selanjutnya, Anda perlu mengimplementasikan kelas PrintNeAnimaladdedListener. Kelas ini menggunakan metode System.out.println untuk mengeluarkan nama hewan baru. Kode spesifiknya adalah sebagai berikut:
kelas publik printNeanimaladdedListener mengimplementasikan animalAddedListener {@Overridepublic void updateanimaladded (hewan hewan) {// cetak nama animal animalsystem.out.println ("Menambahkan hewan baru dengan nama '" + animal.getname () + "");}}Akhirnya, kita perlu menerapkan fungsi utama yang mendorong aplikasi:
Public Class Main {public static void main (string [] args) {// Buat kebun binatang untuk menyimpan binatangzoo zoo = new zoo (); // daftarkan pendengar untuk diberitahu ketika hewan ditambahkan. Hewan ("harimau"));}}Fungsi utama hanya membuat objek kebun binatang, mendaftarkan pendengar yang mengeluarkan nama hewan, dan membuat objek hewan baru untuk memicu pendengar terdaftar. Output akhir adalah:
Menambahkan hewan baru dengan nama 'Tiger'
Menambahkan pendengar
Keuntungan dari mode pengamat sepenuhnya ditampilkan ketika pendengar dibangun kembali dan ditambahkan ke subjek. Misalnya, jika Anda ingin menambahkan pendengar yang menghitung jumlah total hewan di kebun binatang, Anda hanya perlu membuat kelas pendengar tertentu dan mendaftarkannya dengan kelas kebun binatang tanpa modifikasi ke kelas kebun binatang. Menambahkan kode penghitung penghitung penghitung pendengar adalah sebagai berikut:
Public Class CountanimaladdedListener mengimplementasikan animalAddedListener {private static int animalsaddedcount = 0; @Overridepublic void updateanimaladded (hewan hewan) {// bertambah jumlah hewanSsystem.out.println ("Total hewan ditambahkan:" + animalddedcount);}}Fungsi utama yang dimodifikasi adalah sebagai berikut:
public class Main { public static void main (String[] args) {// Create the zoo to store animalsZoo zoo = new Zoo();// Register listeners to be notified when an animal is addedzoo.registerAnimalAddedListener(new PrintNameAnimalAddedListener());zoo.registerAnimalAddedListener(new CountingAnimalAddedListener());// Add an animal Beri tahu pendengar yang terdaftar.Hasil outputnya adalah:
Menambahkan hewan baru dengan nama 'Tiger' Total hewan ditambahkan: 1 Menambahkan hewan baru dengan nama 'singa' Total hewan ditambahkan: 2 Menambahkan hewan baru dengan nama 'beruang' total hewan ditambahkan: 3
Pengguna dapat membuat pendengar apa pun jika hanya memodifikasi kode pendaftaran pendengar. Skalabilitas ini terutama karena subjek dikaitkan dengan antarmuka pengamat, daripada secara langsung terkait dengan ConcreteObserver. Selama antarmuka tidak dimodifikasi, tidak perlu memodifikasi subjek antarmuka.
Kelas internal anonim, fungsi lambda dan pendaftaran pendengar
Peningkatan besar dalam Java 8 adalah penambahan fitur fungsional, seperti penambahan fungsi lambda. Sebelum memperkenalkan fungsi Lambda, Java menyediakan fungsi serupa melalui kelas internal anonim, yang masih digunakan dalam banyak aplikasi yang ada. Dalam mode pengamat, pendengar baru dapat dibuat kapan saja tanpa membuat kelas pengamat tertentu. Misalnya, kelas PrintNeAnimaladdedListener dapat diimplementasikan dalam fungsi utama dengan kelas internal anonim. Kode implementasi spesifik adalah sebagai berikut:
Public Class Main {public static void main (string [] args) {// Buat kebun binatang untuk menyimpan hewan ziakzoo = zoo baru (); // Daftarkan pendengar untuk diberitahu ketika hewan ditambahkan. animalsystem.out.println ("Menambahkan hewan baru dengan nama '" + animal.getName () + "'");}}); // Tambahkan hewan memberi tahu pendengar terdaftar.Demikian pula, fungsi Lambda juga dapat digunakan untuk menyelesaikan tugas -tugas tersebut:
Public Class Main {public static void main (string [] args) {// Buat kebun binatang untuk menyimpan binatangzoo zoo = new zoo (); // daftarkan pendengar untuk diberitahu ketika hewan ditambahkan. listenerszoo.addanimal (hewan baru ("harimau"));}}Perlu dicatat bahwa fungsi lambda hanya cocok untuk situasi di mana hanya ada satu fungsi di antarmuka pendengar. Meskipun persyaratan ini tampaknya ketat, banyak pendengar sebenarnya adalah fungsi tunggal, seperti animaladdedlistener dalam contoh. Jika antarmuka memiliki banyak fungsi, Anda dapat memilih untuk menggunakan kelas dalam anonim.
Ada masalah seperti itu dengan pendaftaran implisit dari pendengar yang dibuat: karena objek dibuat dalam ruang lingkup panggilan pendaftaran, tidak mungkin untuk menyimpan referensi ke pendengar tertentu. Ini berarti bahwa pendengar yang terdaftar melalui fungsi Lambda atau kelas internal anonim tidak dapat dicabut karena fungsi pencabutan memerlukan referensi ke pendengar terdaftar. Cara mudah untuk menyelesaikan masalah ini adalah dengan mengembalikan referensi ke pendengar terdaftar dalam fungsi registeranimaladdedlistener. Dengan cara ini, Anda dapat membatalkan pendaftaran pendengar yang dibuat dengan fungsi Lambda atau kelas internal anonim. Kode metode yang ditingkatkan adalah sebagai berikut:
Public AnimalAddedListener RegisteranimaladdedListener (AnimalAddedListener Listener) {// Tambahkan pendengar ke daftar pendengar terdaftar ini.listeners.add (pendengar); mengembalikan pendengar;}Kode klien untuk interaksi fungsi yang dirancang ulang adalah sebagai berikut:
Public Class Main {public static void main (string [] args) {// Buat kebun binatang untuk menyimpan hewan zouszoo = baru zoo (); // daftarkan pendengar untuk diberitahu ketika hewan ditambahkan diAnimaladdedlistener listener = zoo.registeranimaladdedDistener ((hewani) -> System.out.println (") (" needetnete ("name. "'")); // Tambahkan hewan memberi tahu pendengar terdaftar yang terdaftar.Output hasil saat ini hanya ditambahkan hewan baru dengan nama 'Tiger', karena pendengar telah dibatalkan sebelum hewan kedua ditambahkan:
Menambahkan hewan baru dengan nama 'Tiger'
Jika solusi yang lebih kompleks diadopsi, fungsi register juga dapat mengembalikan kelas penerima sehingga pendengar yang tidak terdaftar dipanggil, misalnya:
kelas publik animalAddedListenerReceipt {private final animalAddedistener listener; public animalAddedListenerReceipt (animalAddedlistener listener) {this.listener = pendengar;} public AnimalAddedListener GetListener () {return this.listener;}Kwitansi akan digunakan sebagai nilai pengembalian fungsi pendaftaran dan parameter input dari fungsi pendaftaran dibatalkan. Saat ini, implementasi kebun binatang adalah sebagai berikut:
Kelas Publik ZoousingReceipt {// ... Atribut dan Konstruktor yang Ada ... Public AnimalAddedListenerReceipt RegisteranImaladdedDistener (AnimalAdedListener Listener) {// Tambahkan pendengar yang baru di -listening. (AnimalAddedListenerReceipt Reception) {// Hapus pendengar dari daftar pendengar terdaftar ini.listeners.remove (receip.getListener ());} // ... metode pemberitahuan yang ada ...}Mekanisme implementasi penerima yang dijelaskan di atas memungkinkan penyimpanan informasi untuk panggilan ke pendengar saat dicabut, yaitu, jika algoritma pendaftaran pencabutan tergantung pada status pendengar ketika subjek mendaftarkan pendengar, status ini akan disimpan. Jika pendaftaran pencabutan hanya memerlukan referensi ke pendengar terdaftar sebelumnya, teknologi penerimaan akan tampak merepotkan dan tidak disarankan.
Selain pendengar khusus yang sangat kompleks, cara paling umum untuk mendaftarkan pendengar adalah melalui fungsi lambda atau melalui kelas internal anonim. Tentu saja, ada pengecualian, yaitu kelas yang berisi subjek mengimplementasikan antarmuka pengamat dan mendaftarkan pendengar yang menyebut target referensi. Kasus seperti yang ditunjukkan pada kode berikut:
public class ZooContainer implements AnimalAddedListener { private Zoo zoo = new Zoo();public ZooContainer () {// Register this object as a listenerthis.zoo.registerAnimalAddedListener(this);}public Zoo getZoo () {return this.zoo;}@Overridepublic void updateAnimalAdded (Animal animal) {System.out.println ("ditambahkan hewan dengan nama '" + animal.getName () + "'");} public static void main (string [] args) {// Buat zoo containerzoocontainer zoocontainer = new zoocontainer ();/ Hewan ("harimau"));}}Pendekatan ini hanya cocok untuk kasus -kasus sederhana dan kodenya tampaknya tidak cukup profesional, dan masih sangat populer dengan pengembang Java modern, jadi perlu untuk memahami cara kerja contoh ini. Karena zoocontainer mengimplementasikan antarmuka animaladdedlistener, maka instance (atau objek) zoocontainer dapat didaftarkan sebagai animaladdedlistener. Di kelas Zoocontainer, referensi ini mewakili contoh objek saat ini, yaitu, zoocontainer, dan dapat digunakan sebagai animaladdedlistener.
Secara umum, tidak semua kelas kontainer diperlukan untuk mengimplementasikan fungsi -fungsi tersebut, dan kelas kontainer yang mengimplementasikan antarmuka pendengar hanya dapat memanggil fungsi pendaftaran subjek, tetapi cukup lulus referensi ke fungsi register sebagai objek pendengar. Dalam bab -bab berikut, FAQ dan solusi untuk lingkungan multithreaded akan diperkenalkan.
OnePM memberi Anda solusi kinerja aplikasi Java end-to-end. Kami mendukung semua kerangka kerja Java yang umum dan server aplikasi untuk membantu Anda dengan cepat menemukan kemacetan sistem dan menemukan akar penyebab kelainan. Penempatan pada level kecil dan pengalaman secara instan, pemantauan Java tidak pernah semudah ini. Untuk membaca lebih banyak artikel teknis, silakan kunjungi blog teknologi resmi ONEAPM.
Konten di atas memperkenalkan konten yang relevan dari penggunaan Java 8 untuk mengimplementasikan mode pengamat (Bagian 1). Artikel berikutnya memperkenalkan metode menggunakan Java 8 untuk mengimplementasikan mode pengamat (Bagian 2). Teman yang tertarik akan terus belajar, berharap ini akan membantu semua orang!