1、定义
Define a one-to-many dependcy between objects so that when one object change state, all its dependents are notified and updated automaticallly.
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
2、使用场景
- 关联行为场景,注意,关联行为是可拆分的,而不是“组合”关系
- 事件多触发场景
- 跨系统的消息交换场景,如:消息队列、事件总线的处理机制
3、UML类图
角色说明:
- 抽象主题Subject:被观察者的抽象接口,定义了增加和删除观察者对象
- 具体主题ConcreteSubject:具体的被观察者,将所有的具体的观察者登记在一个列表中,当内部状态改变时,给所有登记的观察者发出通知
- 抽象观察者Observer:观察者接口,定义了在主题改变时通知自己的接口
- 具体观察者ConcreteObserver:实现更新接口
4、示例
以Java中的控件点击事件为例,具体如下:
/**
*
*Clickable 接口对可单击控件功能方法进行了抽象
*相当 观察者模式的Subjuct
*/
public interface Clickable {
public void click();
public void addClickableObserver(ClickableObserver observer);
public void removeClickableObserver(ClickableObserver observer);
}
/**
* ClickableObserver 代表可控按键的观察者
* 相当于观察者模式中的Observer
*
*/
public interface ClickableObserver {
// 更新
public void clicked(Clickable clickable);
}
import java.util.ArrayList;
import java.util.List;
/**
* Button 是按钮控件,Button是可点击的,实现了Clickable接口
* 相当于观察者模式中的ConcreteClickable
*/
public class Button implements Clickable {
private List<ClickableObserver> observers = new ArrayList<>();
// 按钮信息
String color; // 颜色
@Override
public void click() {
System.out.println("按钮被点击了");
for(ClickableObserver observer : observers){
observer.clicked(this);
}
}
@Override
public void addClickableObserver(ClickableObserver observer) {
observers.add(observer);
}
@Override
public void removeClickableObserver(ClickableObserver observer) {
observers.remove(observer);
}
@Override
public String toString() {
return "Button [color=" + color + "]";
}
}
/**
* ChangeColorObserver 修改按钮的颜色值
* 相当观察者模式的ConcreteObserver
*/
public class ChangeColorObserver implements ClickableObserver {
@Override
public void clicked(Clickable clickable) {
Button button = (Button) clickable;
button.color = "红色";
}
}
/**
* OtherObserver 是其他某种业务操作的观察者
* 相当观察者模式的ConcreteObserver
*
*/
public class OtherObserver implements ClickableObserver {
@Override
public void clicked(Clickable clickable) {
System.out.println("执行其他操作");
}
}
/**
* Client 测试点击事件
*
*/
public class Client {
public static void main(String[] args) {
Button button = new Button();
button.color = "白色";
button.addClickableObserver(new ChangeColorObserver());
button.addClickableObserver(new OtherObserver());
button.click();
System.out.println(button.toString());
}
}
结果输出如下:
按钮被点击了
执行其他操作
Button [color=红色]
5、总结
优点:
- 观察者和被观察者之间是抽象耦合的
- 增加系统灵活性,可扩展性
缺点:
- 在Java中消息通知默认是顺序执行的,一个观察者卡顿,会影响整个的执行效率。在这种情况下,采用异步的方式。