观察者模式定义:
定义一个对象间的一对多的依赖关系。当一个对象的状态发生改变,所有依赖于它的对象都得到通知并被自动更新。
Subject :目标对象
一个目标对象有多个观察者观察
提供观察者的添加和删除维护
目标发生变化时通知所有的观察者
Observer:观察者的接口,提供目标通知时对应的更新方法
ConcreteSubject:具体的目标对象
ConcreteObserver:具体的观察者对象
Subject类:
package com.light.com;
import java.util.ArrayList;
import java.util.List;
public class Subject {
private List<Observer> observers = new ArrayList<Observer>();
public void attach(Observer o) {
observers.add(o);
}
public void detach(Observer o) {
observers.remove(o);
}
protected void notifyObservers() {
for (Observer o : observers) {
o.update(this);
}
}
}
Observer接口:
package com.light.com;
public interface Observer {
//更新消息
public void update(Subject subject);
}
ConcreteSubject类:
package com.light.com;
public class ConcreteSubject extends Subject {
//有新消息
private String news;
public String getNews() {
return news;
}
public void setNews(String news) {
this.news = news;
System.out.println("探子回来了,有重要消息");
this.notifyObservers();
}
}
ConcreteObserver类:
package com.light.com;
public class ConcreteObserver implements Observer {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void update(Subject subject) {
//打印新消息
System.out.println(name+"收到了消息,内容是:"+((ConcreteSubject)subject).getNews());
}
}
客户端:
package com.light.com;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
ConcreteSubject paper = new ConcreteSubject();
ConcreteObserver reader1 = new ConcreteObserver();
reader1.setName("孙权");
ConcreteObserver reader2 = new ConcreteObserver();
reader2.setName("刘备");
ConcreteObserver reader3 = new ConcreteObserver();
reader3.setName("织田信长");
paper.attach(reader1);
paper.attach(reader2);
paper.attach(reader3);
paper.setNews("曹操到了");
System.out.println("--------------");
paper.setNews("曹操回去了");
}
}
运行结果:
探子回来了,有重要消息
孙权收到了消息,内容是:曹操到了
刘备收到了消息,内容是:曹操到了
织田信长收到了消息,内容是:曹操到了
--------------
探子回来了,有重要消息
孙权收到了消息,内容是:曹操回去了
刘备收到了消息,内容是:曹操回去了
织田信长收到了消息,内容是:曹操回去了
分析一下流程:假设一个探子持有三方统帅的军令,一旦有新消息立即更新自己的信息库并通知所有统帅我的信息库有更新快来看看,统帅都有探子的引用便于观察。一旦信息库更新,统帅可以根据这个引用看到探子更新的最新信息。主帅依赖于探子得到情报,但探子不依赖于主帅,比如探子觉得某个统帅的工资给低了,不愿帮他做事,就把这个统帅从中去除,去除的统帅也就无法得到信息了。主帅总是被动的等到探子回报信息。
通常我们在JAVA中实现观察者模式,只需要继承系统提供的2个类Observable类和Observer类,其他工作系统已经帮我们封装好了
ConcreteSubject类
package com.light.com;
public class LingLingQi extends java.util.Observable {
private String news;
public String getNews() {
return news;
}
public void setNews(String news) {
this.news = news;
//有新消息了更新消息库
this.setChanged();
//通知统帅吧 这里可以选择只通知这个新消息,而不给统帅自己的引用,可能有其他的消息很宝贵不能给统帅自己留着
this.notifyObservers(news);
//把自己所有的信息暴露给统帅,毫无保留
// this.notifyObservers();
}
}
ConcreteObserver类
package com.light.com;
import java.util.Observable;
public class General implements java.util.Observer {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(name+"收到了消息:"+arg);
}
}
Client客户端
package com.light.com;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
LingLingQi l = new LingLingQi();
General wuTian = new General();
wuTian.setName("武田信玄");
General shangShan = new General();
shangShan.setName("上杉谦信");
General yiDa = new General();
yiDa.setName("伊达政宗");
l.addObserver(wuTian);
l.addObserver(shangShan);
l.addObserver(yiDa);
l.setNews("信长挂了");
System.out.println("------几天后");
l.setNews("羽柴秀吉来了");
}
}
运行结果:
伊达政宗收到了消息:信长挂了
上杉谦信收到了消息:信长挂了
武田信玄收到了消息:信长挂了
------几天后
伊达政宗收到了消息:羽柴秀吉来了
上杉谦信收到了消息:羽柴秀吉来了
武田信玄收到了消息:羽柴秀吉来了
android中的各种事件监听就用到了观察者模式,只是一个观察者观察了多个目标对象,就好比统帅派出了多个探子,每个探子都通过不同的接口通知统帅信息发生了变化。