设计模式之观察者模式—Observer
出版社+订阅者=观察者模式
报社的业务是出版报纸。
向某家报社订阅报纸,只要他们有新报纸出版,就会送给你。
当你不想再看报纸时,取消订阅。报社就不会再给你送报纸。
报社运营中,就会不断有人向他们订阅或取消报纸。
报社:主题(Subject)
订阅者:观察者(Observer)
观察者模式:
定义了对象之间的一对多依赖,当主题对象改变状态时,它的所有观察者都会收到通知并自动更新。
报社+订阅者 案例:
//主题 是数据持有者
public interface Subject {
public void addObserver(Observer o); //增加一个观察者
public void deleteObserver(Observer o);//移除一个观察者
public void notifyObservers();//通知所有观察者
}
//实现类代表一个观察者,观察者必须实现此接口,以便接受通知。
public interface Observer {
/**
* 当主题状态发生改变时,由主题调用此方法,通知观察者。
* @param args 传递给观察者的更新数据。
*/
void update(Object...args);
}
/**
* 出版社
*/
public class Publisher implements Subject {
private ArrayList<Observer> subscribers=new ArrayList<Observer>(); //很多订阅者(观察者)
private String entertainment; //娱乐新闻
private String sports; //体育新闻
public void addObserver(Observer o) {
this.subscribers.add(o);
}
public void deleteObserver(Observer o) {
int i= subscribers.indexOf(o);
if(i>=0) subscribers.remove(o);
}
public void notifyObservers() {
for(Observer ob:subscribers){
ob.update(entertainment,sports);
}
}
//数据发生变化后,通知订阅者
public void changed(){
this.notifyObservers();
}
//更新新闻
public void UpdateNews(String entertainment,String sports){
this.entertainment=entertainment;
this.sports=sports;
this.changed();
}
}
public class Subscriber01 implements Observer{
public void update(Object... args) {
//订阅者 收到新闻更新消息
for(Object o:args){
System.out.println("正在看新闻:"+o);
}
}
}
public class Test01 {
@Test
public void test(){
Publisher publisher=new Publisher();
//增加订阅者
Subscriber01 sb01=new Subscriber01();
Subscriber01 sb02=new Subscriber01();
publisher.addObserver(sb01);
publisher.addObserver(sb02);
//报社更新新闻,自动通知所有订阅者
String entertainment="20后,大话西游,重制后上映!!";
String sports="马云加入了国家太极队";
publisher.UpdateNews(entertainment, sports);
}
}
JDK内置的观察者模式API
在JDK的观察者模型中,主题对象被称为可观察对象Observable。
用JDK的观察者模式API实现上面的例子
public class Publisher extends java.util.Observable{
private String entertainment;
private String sports;
public void UpdateNews(String entertainment,String sports){
this.entertainment=entertainment;
this.sports=sports;
this.setChanged(); //标记,可观察对象(主题对象)已经改变
//拉模型通知所有订阅者
//订阅者需要自己通过getter方法从主体对象中获取自己感兴趣的数据,
this.notifyObservers();
}
public String getEntertainment() {
return entertainment;
}
public String getSports() {
return sports;
}
}
public class Subscriber implements java.util.Observer {
// 用拉模型 从主题对象只获取自己感兴趣的数据
public void update(Observable o, Object arg) {
if(o instanceof Publisher){
Publisher pub=(Publisher)o;
//订阅者只拉取自己感兴趣的娱乐新闻
System.out.println(pub.getEntertainment());
}
}
}
public class Test01 {
@Test
public void test(){
Publisher publisher=new Publisher();
//增加订阅者
Subscriber sb=new Subscriber();
publisher.addObserver(sb);
//报社更新新闻,自动通知所有订阅者
String entertainment="20后,大话西游,重制后上映!!";
String sports="马云加入了国家太极队";
publisher.UpdateNews(entertainment, sports);
}
}