全面解析Java觀察者模式
【正文】
一、觀察者模式的定義:
簡(jiǎn)單地說,觀察者模式定義了一個(gè)一對(duì)多的依賴關(guān)系,讓一個(gè)或多個(gè)觀察者對(duì)象監(jiān)聽一個(gè)主題對(duì)象。這樣一來,當(dāng)被觀察者狀態(tài)發(fā)生改變時(shí),需要通知相應(yīng)的觀察者,使這些觀察者對(duì)象能夠自動(dòng)更新。例如:GUI中的事件處理機(jī)制采用的就是觀察者模式。
二、觀察者模式的實(shí)現(xiàn):
Subject(被觀察的對(duì)象接口):規(guī)定ConcreteSubject的統(tǒng)一接口 ; 每個(gè)Subject可以有多個(gè)Observer;ConcreteSubject(具體被觀察對(duì)象):維護(hù)對(duì)所有具體觀察者的引用的列表 ;–狀態(tài)發(fā)生變化時(shí)會(huì)發(fā)送通知給所有注冊(cè)的觀察者。Observer(觀察者接口):規(guī)定ConcreteObserver的統(tǒng)一接口;定義了一個(gè)update()方法,在被觀察對(duì)象狀態(tài)改變時(shí)會(huì)被調(diào)用。ConcreteObserver(具體觀察者):維護(hù)一個(gè)對(duì)ConcreteSubject的引用;特定狀態(tài)與ConcreteSubject同步;實(shí)現(xiàn)Observer接口,update()方法的作用:一旦檢測(cè)到Subject有變動(dòng),就更新信息。
圖表描述如下:

注:在被觀察者類中需要有一個(gè)集合維護(hù)所有觀察者。
三、舉例說明:
【方案一】:自己定義接口或者類來實(shí)現(xiàn)觀察者模式。
步驟如下:
(1)定義被觀察者所具有的接口:
package com.vince.observer;
public interface Observable {
//注冊(cè)為一個(gè)觀察者
public void registerObserver(Observer observer);
//取消觀察者
public void removeObserver(Observer observer);
//通知所有觀察者更新信息
public void notifyObservers();
}
(2)定義具體的被觀察者:杯子
package com.vince.observer;
import java.util.Vector;
public class Cup implements Observable{
//被觀察者維護(hù)的一個(gè)觀察者對(duì)象列表
private Vector<Observer> vector = new Vector<Observer>();
private float price;
public Cup(float price){
this.price = price;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
//修改價(jià)格時(shí),通知所有觀察者
this.price = price;
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
//注冊(cè)觀察者
vector.add(observer);
}
@Override
public void removeObserver(Observer observer) {
//取消觀察者
vector.remove(observer);
}
@Override
public void notifyObservers() {
//實(shí)現(xiàn)通知所有的觀察者對(duì)象
for (Observer observer:vector) {
observer.update(price);
}
}
}
(3)定義觀察者所具有的共同的接口:(更新數(shù)據(jù)最終當(dāng)然是在觀察者那里進(jìn)行啦)
package com.vince.observer;
public interface Observer {
public void update(float price);5
}
(4)定義具體的觀察者對(duì)象:
package com.vince.observer;
public class Person implements Observer{
private String name;
public Person(String name){
this.name = name;
}
@Override
public void update(float price) {
System.out.println(name+"關(guān)注的杯子的價(jià)格已更新為:"+price);
}
}
(5)測(cè)試:
package com.vince.observer;
public class Test {
public static void main(String[] args) {
//創(chuàng)建一個(gè)被觀察者對(duì)象
Cup doll = new Cup(3000);
//創(chuàng)建兩個(gè)觀察者對(duì)象
Person p1 = new Person("生命壹號(hào)");
Person p2 = new Person("生命貳號(hào)");
//注冊(cè)成為一個(gè)觀察者
doll.registerObserver(p1);
doll.registerObserver(p2);
System.out.println("第一輪促銷:");
doll.setPrice(2698);// 價(jià)格變動(dòng)
System.out.println("第二輪促銷:");
doll.setPrice(2299);//
System.out.println("第三輪促銷:");
doll.setPrice(1998);
doll.removeObserver(p2); //將生命二號(hào)移除
System.out.println("第四輪促銷:");
doll.setPrice(1098);
}
}
運(yùn)行后,顯示結(jié)果如下:

【方案二】:直接調(diào)用JDK的API去實(shí)現(xiàn)。
步驟如下:
(1) 通過繼承Observable類實(shí)現(xiàn)具體的被觀察者對(duì)象:
package com.vince.observer2;
import java.util.Observable;
public class Cup extends Observable{
private float price;
public Cup(float price){
this.price = price;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
this.setChanged();//通知,數(shù)據(jù)已改變
this.notifyObservers();
}
}
(2)通過實(shí)現(xiàn)java.util.Observer接口實(shí)現(xiàn)具體的觀察者對(duì)象:
package com.vince.observer2;
import java.util.Observable;
import java.util.Observer;
public class Person implements Observer{
private String name;
public Person(String name){
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
if(o instanceof Cup){
Cup cup = (Cup)o;
System.out.println(name+"關(guān)注的杯子價(jià)格已更新為:"+cup.getPrice());
}
}
}
(3)測(cè)試:
package com.vince.observer2;
public class Test {
public static void main(String[] args) {
Cup cup = new Cup(3000);
Person p1 = new Person("生命壹號(hào)");
Person p2 = new Person("生命貳號(hào)");
cup.addObserver(p1);
cup.addObserver(p2);
System.out.println("第一輪促銷");
cup.setPrice(2988);
System.out.println("第二輪促銷");
cup.setPrice(2698);
cup.deleteObserver(p2);
System.out.println("第三輪促銷");
cup.setPrice(1998);
}
}
運(yùn)行后,結(jié)果如下:

【工程文件】
鏈接:http://xiazai.jb51.net/201609/yuanma/JavaSEguancha(jb51.net).rar
四、總結(jié):(觀察者模式的作用)
觀察者模式在被觀察者和觀察者之間建立一個(gè)抽象的耦合。被觀察者角色所知道的只是一個(gè)具體觀察者列表。
由于被觀察者和觀察者沒有緊密地耦合在一起,因此它們可以屬于不同的抽象化層次。如果被觀察者和觀察者都被扔到一起,那么這個(gè)對(duì)象必然跨越抽象化和具體化層次。
觀察者模式支持廣播通訊。被觀察者會(huì)向所有的登記過的觀察者發(fā)出通知。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 使用Java8實(shí)現(xiàn)觀察者模式的方法(上)
- 實(shí)例解析觀察者模式及其在Java設(shè)計(jì)模式開發(fā)中的運(yùn)用
- 用Java設(shè)計(jì)模式中的觀察者模式開發(fā)微信公眾號(hào)的例子
- 深入解析Java設(shè)計(jì)模式編程中觀察者模式的運(yùn)用
- 全面解析Java8觀察者模式
- Java設(shè)計(jì)模式開發(fā)中使用觀察者模式的實(shí)例教程
- 學(xué)習(xí)Java設(shè)計(jì)模式之觀察者模式
- 輕松掌握J(rèn)ava觀察者模式
- java設(shè)計(jì)模式之觀察者模式
- java設(shè)計(jì)模式之觀察者模式學(xué)習(xí)
相關(guān)文章
Spring中的@EnableWebSecurity注解詳解
這篇文章主要介紹了Spring中的@EnableWebSecurity注解詳解,EnableWebSecurity注解是個(gè)組合注解,它的注解中,又使用了@EnableGlobalAuthentication注解,需要的朋友可以參考下2023-12-12
詳解Springboot整合Dubbo之代碼集成和發(fā)布
本篇文章主要介紹了Springboot整合Dubbo之代碼集成和發(fā)布,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12
Java多線程之鎖的強(qiáng)化學(xué)習(xí)
Java多線程的鎖都是基于對(duì)象的,Java中的每一個(gè)對(duì)象都可以作為一個(gè)鎖。這篇文章主要來通過一下示例為大家強(qiáng)化一下鎖的相關(guān)知識(shí)的掌握,希望對(duì)大家有所幫助2023-02-02
PostgreSQL Docker部署+SpringBoot集成方式
本文介紹了如何在Docker中部署PostgreSQL和pgadmin,并通過SpringBoot集成PostgreSQL,主要步驟包括安裝PostgreSQL和pgadmin,配置防火墻,創(chuàng)建數(shù)據(jù)庫(kù)和表,以及在SpringBoot中配置數(shù)據(jù)源和實(shí)體類2024-12-12
Java 動(dòng)態(tài)生成類和實(shí)例, 并注入方法操作示例
這篇文章主要介紹了Java 動(dòng)態(tài)生成類和實(shí)例, 并注入方法操作,結(jié)合實(shí)例形式分析了Java 動(dòng)態(tài)生成類和實(shí)例以及動(dòng)態(tài)注入相關(guān)操作技巧,需要的朋友可以參考下2020-02-02

