定义
对象之间的一对多依赖,当一个对象改变状态时,它所有依赖者都会收到通知并自动更新。
特点
1.需要观察者(observer)和被观察者(observable)组成 ;
2.一般写法为被观察者数量为1,观察者数量可为多个。
适用范围
一般为通知类型的,比如主题订阅更新通知、朋友圈更新通知。
推荐写法
一般有两种写法,一种是直接继承安卓原生的observable类和实现相应的observer接口;另一种是自己写observable和observer接口,并实现。前者使用方便,缺点是继承类违背了设计模式的多使用组合原则,后者就稍微麻烦点咯。以下以自己写接口为例,讲讲一般的写法。
- 被观察者和观察者的接口如下:
public interface Observable {
// 注册观察者函数,注意这里的Observer为接口,之后的参数传递为实现了该接口的类
public void registerObserver(Observer observer);
// 移除观察者
public void removeObserver(Observer observer);
// 被观察者被改变通知所有观察者
public void notifyObservers();
}
public interface Observer {
// 观察者更新,以更新字符串为例
public void update(String s);
}
- 以广播新闻为例,被观察者和观察者的具体实现类如下:
import java.util.ArrayList;
public class Broadcaster implements Observable {
private ArrayList observers;
// 新闻通知
private String todayNews;
// 构造函数,产生广播对象时就创建一个空的数组来存储观察者
public Broadcaster() {
this.observers = new ArrayList();
}
// 设置新闻函数,当新闻发生改变时通知所有观察者
public void setTodayNews(String todayNews) {
this.todayNews = todayNews;
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
// 添加观察者到list中
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
// 移除某个观察者
int index = observers.indexOf(observer);
if (index >= 0) {
observers.remove(index);
}
}
@Override
public void notifyObservers() {
// 通知所有观察者
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer) observers.get(i);
// 因为观察者类都必须实现了update(),所以这里调用的是具体实现了的update()
observer.update(todayNews);
}
}
}
public class Receiver implements Observer {
private String todayNews;
@Override
public void update(String todayNews) {
this.todayNews = todayNews;
// 打印出更新的信息
System.out.println(todayNews);
}
}
观察者模式测试
public class Main {
public static void main(String[] args) {
Broadcaster broadcaster = new Broadcaster();
Receiver receiver1 = new Receiver();
Receiver receiver2 = new Receiver();
// 添加两个观察者到被观察者中
broadcaster.registerObserver(receiver1);
broadcaster.registerObserver(receiver2);
// 被观察者状态改变
broadcaster.setTodayNews("Hello, world!");
System.out.println("-------------------");
// 被观察者移除一个观察者后,状态改变
broadcaster.removeObserver(receiver1);
broadcaster.setTodayNews("Hello, world!");
}
}
Hello, world!
Hello, world!
-------------------
Hello, world!