1. Gambaran keseluruhan
Dalam artikel ini, kita akan menerangkan corak Observer dan melihat beberapa alternatif pelaksanaan Java.
2. Apakah Corak Pemerhati?
Pemerhati adalah corak reka bentuk tingkah laku. Ia menyatakan komunikasi antara objek: diperhatikan dan pemerhati . Yang dapat dilihat adalah objek yang memberitahu pemerhati mengenai perubahan keadaannya.
Sebagai contoh, sebuah agensi berita dapat memberitahu saluran ketika menerima berita. Menerima berita adalah apa yang mengubah keadaan agensi berita, dan menyebabkan saluran diberitahu.
Mari lihat bagaimana kita dapat melaksanakannya sendiri.
Pertama, mari tentukan kelas NewsAgency :
public class NewsAgency { private String news; private List channels = new ArrayList(); public void addObserver(Channel channel) { this.channels.add(channel); } public void removeObserver(Channel channel) { this.channels.remove(channel); } public void setNews(String news) { this.news = news; for (Channel channel : this.channels) { channel.update(this.news); } } }
NewsAgency dapat dilihat, dan ketika berita dikemas kini, keadaan NewsAgency berubah. Apabila perubahan berlaku, NewsAgency memberitahu pemerhati mengenai fakta ini dengan memanggil kaedah kemas kini mereka () .
Untuk dapat melakukan itu, objek yang dapat diamati perlu merujuk kepada pemerhati , dan dalam kes kami, ia adalah pemboleh ubah saluran .
Sekarang mari kita lihat bagaimana pemerhati , yang Channel kelas, boleh kelihatan seperti. Ia harus mempunyai kaedah pembaruan () yang dipanggil ketika keadaan NewsAgency berubah:
public class NewsChannel implements Channel { private String news; @Override public void update(Object news) { this.setNews((String) news); } }
Antara muka Saluran hanya mempunyai satu kaedah:
public interface Channel { public void update(Object o); }
Sekarang, jika kita menambahkan contoh NewsChannel ke daftar pemerhati , dan mengubah keadaan NewsAgency , contoh NewsChannel akan diperbarui:
NewsAgency observable = new NewsAgency(); NewsChannel observer = new NewsChannel(); observable.addObserver(observer); observable.setNews("news"); assertEquals(observer.getNews(), "news");
Terdapat antara muka Observer yang telah ditentukan di perpustakaan inti Java, yang menjadikan pelaksanaan corak pemerhati lebih mudah. Mari lihat.
3. Pelaksanaan Dengan Pemerhati
Antara muka java.util.Observer menentukan kaedah kemas kini () , jadi tidak perlu menentukannya sendiri seperti yang kita lakukan di bahagian sebelumnya.
Mari lihat bagaimana kita dapat menggunakannya dalam pelaksanaan kita:
public class ONewsChannel implements Observer { private String news; @Override public void update(Observable o, Object news) { this.setNews((String) news); } }
Di sini, hujah kedua berasal dari Observable seperti yang akan kita lihat di bawah.
Untuk menentukan yang dapat diperhatikan , kita perlu memperluas kelas Observable Java :
public class ONewsAgency extends Observable { private String news; public void setNews(String news) { this.news = news; setChanged(); notifyObservers(news); } }
Perhatikan bahawa kita tidak perlu memanggil kaedah kemas kini () pemerhati secara langsung. Kami hanya memanggil setChanged () dan notifyObservers () , dan diperhatikan kelas melakukan yang lain untuk kita.
Juga, ia mengandungi senarai pemerhati dan mendedahkan kaedah untuk mengekalkan senarai itu - addObserver () dan deleteObserver ().
Untuk menguji hasilnya, kita hanya perlu menambahkan pemerhati ke senarai ini dan menetapkan berita:
ONewsAgency observable = new ONewsAgency(); ONewsChannel observer = new ONewsChannel(); observable.addObserver(observer); observable.setNews("news"); assertEquals(observer.getNews(), "news");
Antara muka pemerhati tidak sempurna dan tidak digunakan lagi sejak Java 9. Salah satu keburukannya ialah Observable bukan antara muka tetapi kelas, sebab itulah subkelas tidak dapat digunakan sebagai pemerhatian.
Juga, pemaju boleh mengatasi sebahagian daripada diperhatikan 's kaedah disegerakkan dan mengganggu thread-keselamatan mereka.
Mari lihat antara muka ProperyChangeListener , yang disyorkan dan bukannya menggunakan Observer .
4. Pelaksanaan Dengan PropertyChangeListener
Dalam pelaksanaan ini, yang dapat diamati harus menyimpan rujukan ke contoh PropertyChangeSupport . Ini membantu menghantar pemberitahuan kepada pemerhati apabila harta kelas diubah.
Mari kita tentukan yang dapat diperhatikan:
public class PCLNewsAgency { private String news; private PropertyChangeSupport support; public PCLNewsAgency() { support = new PropertyChangeSupport(this); } public void addPropertyChangeListener(PropertyChangeListener pcl) { support.addPropertyChangeListener(pcl); } public void removePropertyChangeListener(PropertyChangeListener pcl) { support.removePropertyChangeListener(pcl); } public void setNews(String value) { support.firePropertyChange("news", this.news, value); this.news = value; } }
Dengan menggunakan sokongan ini , kita dapat menambah dan membuang pemerhati, dan memberitahu mereka apabila keadaan yang dapat dilihat berubah:
support.firePropertyChange("news", this.news, value);
Di sini, hujah pertama adalah nama harta benda yang diperhatikan. Argumen kedua dan ketiga adalah nilai lama dan barunya.
Pemerhati harus melaksanakan PropertyChangeListener :
public class PCLNewsChannel implements PropertyChangeListener { private String news; public void propertyChange(PropertyChangeEvent evt) { this.setNews((String) evt.getNewValue()); } }
Oleh kerana kelas PropertyChangeSupport yang melakukan pendawaian untuk kami, kami dapat memulihkan nilai harta baru dari acara tersebut.
Mari uji pelaksanaannya untuk memastikan bahawa ia juga berfungsi:
PCLNewsAgency observable = new PCLNewsAgency(); PCLNewsChannel observer = new PCLNewsChannel(); observable.addPropertyChangeListener(observer); observable.setNews("news"); assertEquals(observer.getNews(), "news");
5. Kesimpulan
Dalam artikel ini, kami telah mengkaji dua cara untuk menerapkan corak reka bentuk Observer di Java, dengan pendekatan PropertyChangeListener lebih disukai.
Kod sumber untuk artikel tersebut terdapat di GitHub.