观察者模式
定义
- 又叫做发布订阅模式。项目中经常使用。
- 定义了对象间的一对多的依赖关系,每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
观察者模式的优点
- 观察者和被观察者之间是抽象耦合。耦合关系通过接口来维系。
- 支持广播通信。
观察者模式的缺点
- 如果一个主题有多个直接或者间接的观察者,则通知所有的观察者会花费很多时间,且开发和调试都比较复杂。
- 如果主题之间有循环依赖,被观察者会触发它们之间进行循环调用,导致系统崩溃。
- 如果对观察者的通知是通过另外的线程进行异步投递的,系统必须保证投递的顺序执行。
- 虽然观察者模式可以随时使观察者知道所观察的对象发生改变,但是没有提供相应的机制感知变化的形式。
观察者模式的应用场景
- 关联行为场景。
- 事件多级触发场景。
- 跨系统的消息交换场景。如消息队列的处理机制。
观察者模式的注意事项
- 广播链问题。一个观察者可以存在双重身份,既是观察者,又是被观察者,此时链路就会比较复杂,应保证最多只有一个双重身份的对象。
- 异步处理问题。需要考虑线程安全和队列的问题。
代码
被观察者接口
public interface Clickable {
// 单击
void click();
// 添加单击事件的观察者
void addClickableObserver(ClickableObserver clickableObserver);
// 移除单击事件的观察者
void removeClickableObserver(ClickableObserver clickableObserver);
}
观察者接口
public interface ClickableObserver {
// 发生单击事件
void clicked(Clickable clickable);
}
被观察者实现类(Button)
public class Button implements Clickable {
// 存储注册过的单击事件观察者
List<ClickableObserver> observers = new ArrayList<>();
//按钮信息
String color; //颜色
int x,y; //坐标
@Override
public void click() {
System.out.println("按钮被单击");
for (int i = 0;i < observers.size();++i){
observers.get(i).clicked(this);
}
}
@Override
public void addClickableObserver(ClickableObserver clickableObserver) {
observers.add(clickableObserver);
}
@Override
public void removeClickableObserver(ClickableObserver clickableObserver) {
observers.remove(clickableObserver);
}
@Override
public String toString() {
return "Button{" +
"observers=" + observers +
", color='" + color + '\'' +
", x=" + x +
", y=" + y +
'}';
}
}
观察者实现类
- 改变颜色观察者
public class ChangeColorObserver implements ClickableObserver{
@Override
public void clicked(Clickable clickable) {
Button b = (Button) clickable;
b.color = "红色";
}
}
- 改变坐标观察者
public class ChangeCoordinateObserver implements ClickableObserver {
@Override
public void clicked(Clickable clickable) {
Button b = (Button) clickable;
b.x = 100;
b.y = 200;
}
}
- 其他观察者
public class OtherObserver implements ClickableObserver {
@Override
public void clicked(Clickable clickable) {
System.out.println("执行其他方法...");
}
}
主逻辑
public class Test {
public static void main(String[] args) {
Button button = new Button();
button.color = "白色";
button.x = 0;
button.y = 1;
button.addClickableObserver(new ChangeColorObserver());
button.addClickableObserver(new ChangeCoordinateObserver());
button.addClickableObserver(new OtherObserver());
button.click();
System.out.println(button);
}
}
执行结果
图示
个人理解
下方三个观察者一直在监听被观察者的事件,一旦被观察者发生click事件,三者都会触发自身的clicked事件进行响应。动作的发生是由上层传向下层的。