观察者模式 Observer
- 场景
- 聊天室程序的创建。服务器创建好后,A,B,C三个客户端连上来公开聊天。A向服务器发送数据,服务器端聊天数据改变。我们希望将这些聊天数据分别发给其他在线的客户。也就是说,每个客户端需要更新服务器端的数据。
- 网站上,很多人订阅了“java主题”的新闻。当有这个主题新闻时,就会将这些新闻发给所有订阅的人。
- 大家一起玩CS游戏时,服务器需要将每个人的方位变化发给所有的客户。
这些场景,我们都可以使用观察者模式来处理。我们可以把多个订阅者、客户称之为观察者;需要同步给多个订阅者的数据封装到对象中,称之为目标。
- 核心
- 观察者模式主要用于1:N的通知。当一个对象(目标对象Subject或Observable)的状态变化时,他需要及时告知一系列对象(观察者对象,Observer),令他们做出响应
- 通知观察者的方式:
- 推
- 每次都会把通知以广播方式发送给所有观察者,所有观察者只能被动接受。
- 拉
- 观察者只要知道有情况即可。至于什么时候获取内容,获取什么内容,都可以自主决定。
- 推
示例代码
package com.yishan.observer;
/**
* 观察者模式
* @author : yishan
* @date : 2020-10-27 20:57
*/
public interface Observer {
void update(Subject subject);
}
package com.yishan.observer;
import java.util.ArrayList;
import java.util.List;
/**
* @author : yishan
* @date : 2020-10-27 20:58
*/
public class Subject {
protected List<Observer> list = new ArrayList<>();
public void registerObserver(Observer obs){
list.add(obs);
}
public void removeObserver(Observer obs){
list.remove(obs);
}
//通知所有的观察者更新状态
public void notifyAllObservers(){
for (Observer obs:list){
obs.update(this);
}
}
}
package com.yishan.observer;
/**
* @author : yishan
* @date : 2020-10-27 21:04
*/
public class ConcreteSubject extends Subject {
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
//主题对象(目标对象)值发生了变化,请通知所有的观察者
this.notifyAllObservers();
}
}
package com.yishan.observer;
/**
* @author : yishan
* @date : 2020-10-27 21:07
*/
public class ObserverA implements Observer {
private int myState; //myState需要跟目标对象的state值保持一致!
@Override
public void update(Subject subject) {
myState = ((ConcreteSubject)subject).getState();
}
public int getMyState() {
return myState;
}
public void setMyState(int myState) {
this.myState = myState;
}
}
开发中常见的场景
- 聊天室程序的,服务器转发给所有客户端
- 网络游戏(多人联机对象)场景中,服务器将客户端的状态进行分发
- 邮件订阅
- Servlet中,监听器的实现
- Android中,广播机制
- JDK的AWT中时间处理模型,基于观察者模式的委派事件模型
- 事件源——-目标对象
- 事件监听器——-观察者
- 京东商城中,群发某商品打折信息