观察者模式
入门须知
观察者又称发布订阅(Publish/Subscribe)模式,听着很熟,记得redis中有pub/sub,vue中好像也学过pub-sub js。
它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,是他们能够自动更新自己。
eg: 关注了csdn的一个博主,当她发布新文章时,可以很快的知道又有新的知识要学了。公众号、订阅号、抖音视频主。。。。。;
专有名词
1.Subject
抽象主题(被观察者),抽象主题角色把所有的观察者对象保存在一个集合中,每个主题可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象
2.ConcreteSubject
具体主题(subject的实现类,就是监视的对象),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知
3.Observer
抽象观察者,观察者的抽象类,定义了一个更新接口,使得在得到主题更改通知时更新自己。
4.ConcreteObserver
具体观察者(用户),实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态
代码实现
以csdn举例
抽象观察者类
//抽象观察者类
public abstract class Observer {
abstract void update(String message);
}
抽象被观察者类
//主题:抽象被观察者
public interface Subject {
/**
* 订阅者
* @param observer
*/
public void attach(Observer observer);
/**
* 删除订阅者
* @param observer
*/
public void detach(Observer observer);
/**
* 通知订阅者更新消息
* @param message
*/
public void notify(String message);
}
具体观察者
//具体观察者:关注博客的人
public class FansUser extends Observer {
//csdn用户名
private String name;
public FansUser(String name) {
this.name = name;
}
@Override
void update(String message) {
System.out.println(name + "-" + message);
}
}
博主,具体主题
public class SubscriptionSubject implements Subject{
/**
* 存储观察者,博主的粉丝
*/
private List<Observer> 优快云UserList = new ArrayList<>();
//添加关注
@Override
public void attach(Observer observer) {
优快云UserList.add(observer);
}
@Override
public void detach(Observer observer) {
优快云UserList.remove(observer);
}
//新发布文章提醒
@Override
public void notify(String message) {
//以广播形式发布:关注的人都可以收到消息
for (Observer observer : 优快云UserList) {
observer.update(message);
}
}
}
测试
public class Test {
public static void main(String[] args) {
SubscriptionSubject subscriptionSubject = new SubscriptionSubject();
//创建三个靓仔粉丝
FansUser user1 = new FansUser("靓仔1");
FansUser user2 = new FansUser("靓仔2");
FansUser user3 = new FansUser("靓仔3");
//关注博主
subscriptionSubject.attach(user1);
subscriptionSubject.attach(user2);
subscriptionSubject.attach(user3);
//通知粉丝
subscriptionSubject.notify("快来给我的文章点赞吧。。。。");
}
}
优点
- 降低目标和观察者之间的耦合关系,两者之间是抽象耦合关系
- 博主发布新文章,所有的粉丝都会收到消息:可以实现广播机制
缺点
- 如果观察者非常多的话,那么所有的观察者收到被观察者发送的通知会耗时
- 如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,会导致系统裂开