观察者模式-Observer
当一个对象变化时,其它依赖该对象的对象都会收到通知, 并且会随着变化!对象之间是一种一对多的关系。
换一种表达方式: 有很多观察者们依赖于(观察)同一个对象(主题), 当这个被依赖的对象(主题)变化时, 观察者们也会随之变化.
本文中的例子如下: 有一个进度生成器, 用来模拟进度条的数值. 当进度数值更新后, 就会通知进度栏更新值. 也就是进度栏是观察者, 随时间在变的进度值是主题内容.
Observer接口
这是观察者的统一定义. 主题被修改时, 通过调用update()方法来通知观察者更新.
/**
* 观察者接口-观察者的统一定义
*/
public interface Observer {
/**
* Observer(观察者)会被数值生成器通知, 来更新自己的状态
*/
void update(ProgressBar generator);
}
DigitObserver类
数字进度类. 这是其中一种观察者的实现, 也是一种具体的进度条.
/**
* 将进度以数字形式展现出来
*/
public class DigitObserver implements Observer {
/**
* Observer(观察者)会被数值生成器通知, 来更新自己的状态
*/
@Override
public void update(ProgressBar generator) {
System.out.println("数字版进度条:" + generator.getNumber() + "%");
}
}
GraphObserver类
图形进度条, 这是其中一种观察者的实现, 也就是一种具体的进度条.
/**
* 将进度条以进度栏形式展现出来
*/
public class GraphObserver implements Observer {
/**
* Observer(观察者)会被数值生成器通知, 来更新自己的状态
*/
@Override
public void update(ProgressBar generator) {
System.out.print("图形版进度条:");
int count = generator.getNumber();
for (int i = 0; i < count; i++) {
System.out.print("*");
}
System.out.println("");
}
}
ProgressBar类
由本类来模拟 随时间在涨的进度数值, 进度值变更后, 会通知进度条来更新自己的值.
/**
* 生成数值的类, 同时会保存观察者们, 当数值生成的时候就会去通知所有观察者们
*/
public class ProgressBar {
/**
* 保存Observer们
*/
private ArrayList observers = new ArrayList<>();
/**
* 当前数值
*/
private int number;
public int getNumber() {
return number;
}
/**
* 生成数值, 并通知给观察者们
*/
public void execute() {
for (int i = 0; i <= 100; i += 10) {
number = i;
notifyObservers();
}
}
/**
* 注册Observer
*/
public void addObserver(Observer observer) {
observers.add(observer);
}
/**
* 向Observer发送通知
*/
public void notifyObservers() {
for (Observer o : observers) {
o.update(this);
}
try {
System.out.println();
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Main
public class Main {
public static void main(String[] args) {
// 进度值
ProgressBar progressBar = new ProgressBar();
// 图形进度条, 和数值进度条 都订阅了这个进度值
// 在进度值变化时, 这两个观察者就会更新自己的进度
progressBar.addObserver(new DigitObserver());
progressBar.addObserver(new GraphObserver());
// 进度值开始变动
progressBar.execute();
}
}
运行结果如下: