1,什么是观察者模式?定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动 更新自己。形象点说就像 有几个人订阅邮件一样,比如订阅腾讯新闻,腾讯新闻就是一个主题(subject),你们每一个人都是一个观察者(observer);可以取消订阅,就不是观察者了,也 可以增加一个订阅的人,这个人就成了观察者,一般观察者有以下几个角色:
如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
首先定抽象主题角色:Subject.java
package observer;
/**
* 抽象主题角色
* @author yt
*
*/
public interface Subject {
/**
* 向主题注册观察者
* @param o
* @author mj
*/
public void registerObserver(Observer o);
/**
* 从主题中删除观察者
* @param o
* @author mj
*/
public void removeObserver(Observer o);
/**
*
* 通知观察者
* @author mj
*/
public void notifyObservers();
}
再定义具体主题角色 TencentSubject.java
package observer;
import java.util.ArrayList;
import java.util.List;
/**
* 腾讯新闻这个主题
* @author yt
*
*/
public class TencentSubject implements Subject {
//主题中要持有所有的观察者,观察这都要被注册到主题中的这个list中
private List list=new ArrayList<>();
//标题和内容,为了观察者能够 使用拉模式(pull)获取自己需要的信息(比如只获取标题,或者只获取内容,或者都获取),提供这两个变量的get/set方法
private String title;
private String content;
@Override
public void registerObserver(Observer o) {
list.add(o);//注册观察者
}
@Override
public void removeObserver(Observer o) {
list.remove(o);//删除观察者
}
@Override
public void notifyObservers() {
for(Observer o:list){
o.update(title, content);//推模式
//o.update(this); //拉模式
}
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
package observer;
/**
* 抽象的观察者角色
* @author yt
* 观察者订阅新闻又分为两种,推送模式(push),和拉取模式(pull)
*/
public interface Observer {
/**
* 1,推送模式,不管观察者需不需要,一股脑的全推送给观察者。
* 观察者向主题订阅自己感兴趣的内容。这里以订阅新闻为列子,当有新的新闻时,主题把 标题,和内容推送给观察者。
* @param title
* @param content
* @author mj
*/
public void update(String title,String content);
/**
* 拉取(pull)模式,一般把主题对象传过来,观察这,根据需要到主题中拉取自己需要的内容,而不是被动的接受 主题推送过来的。
* @param subject
* @author mj
*/
public void update(Subject subject);
}
package observer;
/**
* 观察者张三
* @author yt
*
*/
public class ZhangsanObserver implements Observer {
/**
* 推模式
*/
@Override
public void update(String title, String content) {
System.out.println("我是观察者zhangsan收到的推送消息为:"+title+":"+content);
}
/**
* 拉模式
*/
@Override
public void update(Subject subject) {
System.out.println("我是观察者zhangsan收到的推送消息为:"+((TencentSubject)subject).getTitle());
}
}
package observer;
/**
* 观察者张三
* @author yt
*
*/
public class LishiObserver implements Observer {
/**
* 推模式
*/
@Override
public void update(String title, String content) {
System.out.println("我是观察者lishi收到的推送消息为:"+title+":"+content);
}
/**
* 拉模式
*/
@Override
public void update(Subject subject) {
System.out.println("我是观察者lishi收到的推送消息为:"+((TencentSubject)subject).getTitle());
}
}
客户端调用
package observer;
public class ClientObserver {
public static void main(String[] args) {
//创建主题对象
TencentSubject subject=new TencentSubject();
//创建观察者对象
ZhangsanObserver zhangsan=new ZhangsanObserver();
LishiObserver lishi=new LishiObserver();
//把观察者注册到主题TencentSubject中
subject.registerObserver(zhangsan);
subject.registerObserver(lishi);
//当主题对象改变时(有新的新闻产生时)
subject.setTitle("美国大选");
subject.setContent("特朗普当选为美国总统!");
subject.notifyObservers();//还可以在这个方法中再添加一些逻辑,比如当满足某一条件时,再推送。
}
}
我是观察者zhangsan收到的推送消息为:美国大选:特朗普当选为美国总统!
我是观察者lishi收到的推送消息为:美国大选:特朗普当选为美国总统!
二:jdk自带的观察者模式实现。
jdk 提供了 Observerable /Observer 实现,Observerable 相当于本列的 Subject 只不过他是一个类,而不是一个接口,当需要多继承的时候就没法了,所以说有一定的缺陷。。。