一同波、場(chǎng)景
聊天室程序的創(chuàng)建鳄梅。服務(wù)器創(chuàng)建好之后,A未檩、B戴尸、C三個(gè)客戶端連接上來公開聊天。A向服務(wù)器發(fā)送數(shù)據(jù)冤狡,服務(wù)器端聊天數(shù)據(jù)改變孙蒙。我們希望將這些聊天數(shù)據(jù)分別發(fā)送給其他在線客戶。也就是說悲雳,每個(gè)客戶端需要更新服務(wù)器端的數(shù)據(jù)
網(wǎng)站上挎峦,很多人訂閱“java主題”的新聞。當(dāng)有這個(gè)主題新聞時(shí)合瓢,就會(huì)將這些新聞發(fā)送給所有訂閱的人坦胶。
大家一起玩游戲,服務(wù)器需要將每個(gè)人的訪問變化發(fā)送給所有隊(duì)友晴楔。
上面這些場(chǎng)景顿苇,我們都可以使用觀察者模式來處理。我們可以把多個(gè)訂閱者税弃、客戶端稱之為觀察者纪岁。需要同步給多個(gè)訂閱者的數(shù)據(jù)封裝到對(duì)象中,稱之為目標(biāo)對(duì)象则果。
二幔翰、核心
主要用于:N的通知漩氨。當(dāng)一個(gè)對(duì)象(目標(biāo)對(duì)象
Subject
或Observable
)的狀態(tài)變化時(shí),它需要及時(shí)告知一系列對(duì)象(觀察者對(duì)象Observer
)遗增,使它們做出相關(guān)的響應(yīng)才菠。-
通知觀察者的方式
- 推:每次都會(huì)把通知以廣播方式發(fā)送給所有觀察者,所有觀察者只能被動(dòng)接收
- 拉:觀察者只要知道有情況即可贡定。至于什么時(shí)候獲取內(nèi)容赋访,獲取什么內(nèi)容都可以自主決定。
Observer.java
package cn.itcast.day251.observer;
//觀察者接口
public interface Observer {
public void update(Subject subject);
}
ObserverA.java
package cn.itcast.day251.observer;
public class ObserverA implements Observer{
private int myState ;
//需要跟目標(biāo)對(duì)象的state的值保持一致
public void update(Subject subject) {
myState = ((ConcreteSubject)subject).getState();
}
public int getMyState() {
return myState;
}
public void setMyState(int myState) {
this.myState = myState;
}
}
Subject.java
package cn.itcast.day251.observer;
import java.util.ArrayList;
import java.util.List;
//主題對(duì)象
public class Subject {
protected List<Observer> list = new ArrayList<Observer>();//保存觀察此主題的所有的觀察者對(duì)象
//注冊(cè)新的觀察者
public void register(Observer obs){
if(!list.contains(obs)){
list.add(obs);
}
}
//刪除觀察者
public void remove(Observer obs){
if(list.contains(obs)){
list.remove(obs);
}
}
//通知所有的觀察者更新狀態(tài)
public void notifyAllObserver(){
for (Observer obs : list) {
obs.update(this);
}
}
}
ConcreteSubject.java
package cn.itcast.day251.observer;
public class ConcreteSubject extends Subject{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
this.notifyAllObserver();//主題對(duì)象發(fā)生變化后通知所有的觀察者
}
}
說明:首先給出了觀察者接口和一個(gè)實(shí)現(xiàn)缓待,而這個(gè)實(shí)現(xiàn)中我們維護(hù)了一個(gè)狀態(tài)屬性(myState
)蚓耽,這個(gè)狀態(tài)在后面會(huì)隨著目標(biāo)對(duì)象中的狀態(tài)保持一致。而主題對(duì)象(目標(biāo)對(duì)象)中維護(hù)多個(gè)觀察者旋炒。
Client.java
package cn.itcast.day251.observer;
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();//目標(biāo)對(duì)象
//創(chuàng)建多個(gè)觀察者
ObserverA o1 = new ObserverA();
ObserverA o2 = new ObserverA();
ObserverA o3 = new ObserverA();
ObserverA o4 = new ObserverA();
//將所有觀察者添加到subject對(duì)象的觀察者隊(duì)列中
subject.register(o1);
subject.register(o2);
subject.register(o3);
subject.register(o4);
//改變subject的狀態(tài)
subject.setState(3000);//初始值是0
//觀察者的狀態(tài)
System.out.println(o1.getMyState());
System.out.println(o2.getMyState());
System.out.println(o3.getMyState());
System.out.println(o4.getMyState());
}
}
說明:看以看到當(dāng)目標(biāo)對(duì)象的狀態(tài)變化時(shí)步悠,會(huì)通知所有的觀察者,讓所有觀察者對(duì)象的狀態(tài)都發(fā)生改變瘫镇。
三鼎兽、java中觀察者模式的實(shí)現(xiàn)
javaSE
提供了java.util.Observable和java.util.Observer
來實(shí)現(xiàn)觀察者模式
ConcreteSubject.java
package cn.itcast.day252.observer;
import java.util.Observable;
//目標(biāo)對(duì)象
public class ConcreteSubject extends Observable {
private int state ;
public void set(int s){
state = s;//目標(biāo)對(duì)象的狀態(tài)發(fā)生了改變
setChanged();//表示目標(biāo)對(duì)象已經(jīng)做了更改
notifyObservers(state);//通知所有的觀察者
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
}
ObserverA.java
package cn.itcast.day252.observer;
import java.util.Observable;
import java.util.Observer;
public class ObserverA implements Observer{
private int myState;
@Override
public void update(Observable o, Object arg) {
myState = ((ConcreteSubject)o).getState();
}
public int getMyState() {
return myState;
}
public void setMyState(int myState) {
this.myState = myState;
}
}
Client.java
package cn.itcast.day252.observer;
public class Client {
public static void main(String[] args) {
//創(chuàng)建目標(biāo)對(duì)象
ConcreteSubject subject = new ConcreteSubject();
//創(chuàng)建觀察者
ObserverA o1 = new ObserverA();
ObserverA o2 = new ObserverA();
ObserverA o3 = new ObserverA();
ObserverA o4 = new ObserverA();
//將觀察者對(duì)象添加到目標(biāo)對(duì)象subject的容器中
subject.addObserver(o1);
subject.addObserver(o2);
subject.addObserver(o3);
subject.addObserver(o4);
//改變subject的狀態(tài)
subject.setState(300);
System.out.println(o1.getMyState());
System.out.println(o2.getMyState());
System.out.println(o3.getMyState());
System.out.println(o4.getMyState());
}
}
說明:我們一般還是使用java
自帶的觀察者模式實(shí)現(xiàn)類。