设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)

  1. 定义
  2. 角色
  3. 使用场景
  4. 缺点
  5. Java实现
  6. 总结

定义

当一个对象状态发生改变时,依赖它的所有对象都会得到通知并通知自动更新

角色

抽象主题(Subject):也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。

具体主题(ConcreteSubject):也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。

抽象观察者(Observer):它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。

具体观察者(ConcreteObserver):实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

使用场景

1、存在一对多的对象关系,一个对象改变影响其他对象

2、广播机制。如邮件订阅,公众号订阅、up的关注等

缺点

在观察者过多的时候,通知效率会降低

Java实现

uml类图,可以看到具体目标对象与观察者的耦合很小

img

如何调用

1
2
3
4
5
6
7
8
9
10
//创建目标对象
Subject concreteSubject = new ConcreteSubject();
//创建观察者
Observer o1 = new ConcreteObserver1();
Observer o2 = new ConcreteObserver2();
//将目标对象与观察者关联
concreteSubject.addObserver(o1);
concreteSubject.addObserver(o2);
//目标对象发生变化
concreteSubject.notifyObserver();

抽象主题(目标对象抽象类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class Subject {
//创建观察者集合,protected为了目标对象可以访问到
protected List<Observer> list = new ArrayList<>();

public boolean addObserver(Observer o){
return list.add(o);
}

public boolean removeObserver(Observer o){
return list.remove(o);
}

public abstract void notifyObserver();
}

抽象观察者

1
2
3
4
5
6
7
8
9
10
public class ConcreteSubject extends Subject {
@Override
public void notifyObserver() {
System.out.println("目标对象状态发生改变,通知给所有观察者!");
//所有观察者做出响应
for (Observer o : list) {
o.response();
}
}
}

具体观察者

1
2
3
4
5
6
7
8
9
10
11
12
public class ConcreteObserver1 implements Observer {
@Override
public void response() {
System.out.println("观察者对象1已经收到通知,正在变更状态...");
}
}
public class ConcreteObserver2 implements Observer {
@Override
public void response() {
System.out.println("观察者对象2已经收到通知,正在变更状态...");
}
}

这样一个简单的模式就搭出来了,结果输出

1
2
3
目标对象状态发生改变,通知给所有观察者
观察者对象1已经收到通知,正在变更状态...
观察者对象2已经收到通知,正在变更状态...

总结

监听器类都是观察者模式的一种体现