定义:
观察者模式(又被称为发布-订阅(Publish/Subscribe))模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象.这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己.
举个栗子:
如果你关注了张大仙的直播,每当他开播的时候你就能收到虎牙直播给你推送的张大仙开播的消息
粉丝就是观察者,随时观察主播是否开播。不过主播有权利让你关注,也有权利把你拉黑
模式结构图
从上面我们可以看到,这里面包含了两大类(主题和观察者)一共四个角色:
- Subject:抽象主题,他把所有观察者对象保存在一个集合里,可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。意思就是明星把所有的粉丝都保存在一个账号里面,粉丝数量不限,可以新增粉丝也可以拉黑粉丝。
- ConcreteSubject:具体主题,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。意思是我们的明星一有动态,就会把消息给粉丝。
- Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。这就是我们所有粉丝的抽象。
- ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。具体每一个粉丝。
代码实现
/**
* 抽象观察者(抽象的粉丝)
*/
public interface Observer {
void update(String message);
}
/**
* 具体观察者:具体的粉丝
*/
public class ConcreteObserver implements Observer {
private String fanName;
public ConcreteObserver(String fanName){
this.fanName = fanName;
}
@Override
public void update(String message) {
System.out.println(fanName + "知道了:"+message+"这条消息");
}
}
/**
* 定义抽象主题:抽象明星
*/
public interface Subject {
//增加粉丝
void addFan(Observer fan);
//拉黑粉丝
void deFan(Observer fan);
//告诉粉丝我的动态
void notify(String message);
}
/**
* 具体主题:具体的明星
*/
public class ConcreteSubject implements Subject{
//保存所有的粉丝
private List<Observer>fanList = new ArrayList<>();
@Override
public void addFan(Observer fan) {
fanList.add(fan);//增加粉丝
}
@Override
public void deFan(Observer fan) {
fanList.remove(fan);//拉黑粉丝
}
@Override
public void notify(String message) {
for (Observer fan:fanList){
fan.update(message);//通知每一个粉丝消息
}
}
}
//第一步:有一个明星
ConcreteSubject subject = new ConcreteSubject();
//第二步:有很多粉丝,这里给出来三个吧
ConcreteObserver observer1 = new ConcreteObserver("张三");
ConcreteObserver observer2 = new ConcreteObserver("李四");
ConcreteObserver observer3 = new ConcreteObserver("王五");
//第三步:让粉丝去关注明星(反过来,明星把他们拉进来)
subject.addFan(observer1);
subject.addFan(observer2);
subject.addFan(observer3);
//第四步:明星发动态,粉丝获取动态
subject.notify("张大仙开播");
//输出信息
张三知道了:张大仙开播这条消息
李四知道了:张大仙开播这条消息
王五知道了:张大仙开播这条消息
总结:
观察者模式的主要优点在于可以实现表示层和数据逻辑层的分离,并在观察目标和观察者之间建立一个抽象的耦合,支持广播通信;其主要缺点在于如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间,而且如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
其实还有一点需要我们去了解,在上面的例子当中我们的会发现,其实粉丝的消息是明星推过来的,还有一种观察者模式,也就是我们的粉丝主动去获取消息。
(1)推模型: 主题对象向观察者推送主题的详细信息,不管是否需要。
(2)拉模型:主题对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到主题对象中获取。