观察者模式属于11种行为型设计模式的一种,在实际的开发中用得比较多,需要重点掌握。@mikechen
观察者模式的定义
观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
这种设计模式的思想应用比较广泛,比如在Redis的主从服务器中,当从服务器完成了各种步骤进入与主服务器命令传播的步骤之后,每次主服务器接收到一次外部命令写入,都会把该命令广播给所有的从服务器,背后的实现本质都是观察者的设计思路。
这种一对多的关系就是观察者模式,其中观察者是各个从服务器,被观察者是主服务器。
观察者模式的模型
观察者模式的主要角色如下:
1.抽象主题(Subject)角色
它是指被观察的对象,又称为主题,定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象。
2.具体主题(Concrete Subject)角色
也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
3.抽象观察者(Observer)角色
它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
4.具体观察者(Concrete Observer)角色
实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
观察者模式的实现
1.创建被观察者
package com.mikechen.java.design.observers.model; /** * 被观察者 * * @author mikechen */ public interface Subject { //被观察者至少有三个方法: 添加监听者、删除监听者和通知监听者 public void registerObserver(Observer observer); public void removeObserver(Observer observer); public void notifyAllObserver(); public abstract void doSomething(); }
2.创建具体观察者
package com.mikechen.java.design.observers.model; import java.util.ArrayList; import java.util.List; /** * 具体被观察者 * * @author mikechen */ public class ConcreteSubject implements Subject { //观察者数组 private List<Observer> observers = new ArrayList<>(); @Override public void registerObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { observers.remove(observer); } @Override public void notifyAllObserver() { for (Observer observer : observers){ observer.update(); } } @Override public void doSomething() { System.out.println("具体目标发生改变"); this.notifyAllObserver(); } }
3.创建观察者
package com.mikechen.java.design.observers.model; /** * 观察者 * * @author mikechen */ public interface Observer { //观察者至少有一个方法:更新方法。 public void update(); }
4.创建具体观察者
1)具体观察者1
package com.mikechen.java.design.observers.model; /** * 具体观察者1 * * @author mikechen */ public class ConcreteObserver1 implements Observer{ @Override public void update() { System.out.println("观察者1收到消息,进行处理"); } }
2)具体观察者2
package com.mikechen.java.design.observers.model; /** * 具体观察者2 * * @author mikechen */ public class ConcreteObserver2 implements Observer{ @Override public void update() { System.out.println("观察者2收到消息,进行处理"); } }
观察者模式的优缺
1.观察者模式的优点
1)主题与观察者之间松耦合
观察者模式在被观察者和观察者之间建立一个抽象的耦合。
2)支撑广播通信
被观察者会向所有的登记过的观察者发出通知,一条消息可以通知给多个人。
2.观察者模式的缺点
1)目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
2)如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3)当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
4)如果采用顺序通知,当某个观察者卡住了,其他的观察者将无法接收到通知
观察者模式的应用场景
观察者模式的应用场景非常广泛,小到代码层面的解耦,大到架构层面的系统解耦,都有这种模式的影子。
1、 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、系统存在事件多级触发时。
3、 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
mikechen睿哥
mikechen睿哥,十余年BAT架构经验,资深技术专家,就职于阿里、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》