文章目录
- 观察者模式
- 什么是观察者模式
- 引入
- 组成
- UML图
- 代码实现
- 1. 定义观察者接口
- 2. 定义主题接口
- 3. 实现具体观察者
- 4. 实现具体被观察者
- 5.测试
- 应用场景
- 优点
- 缺点
观察者模式
什么是观察者模式
观察者模式(Observer Pattern)是一种设计模式
它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象
使得当一个对象的状态发生改变时,其依赖的其他对象会被自动通知和更新。
引入
假如你有两种类型的对象:
顾客
和商店
。 顾客对某个产品非常感兴趣 , 而该产品很快将会在商店里出售。顾客可以每天来商店看看产品是否到货。 但如果商品尚未到货时, 绝大多数来到商店的顾客都会空手而归。因此,每次产品到货时, 商店可以向订阅的顾客发送邮件。 这样, 顾客就无需反复前往商店
假设有一个微信公众号,当微信公众号发布新文章时,所有关注的用户都会收到推送。
组成
由以下四部分组成:
-
Subject
:抽象主题(抽象被观察者)抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者
抽象主题提供一个接口,可以增加和删除观察者对象。
-
Concretesubject
:具体主题(具体被观察者)该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
-
observer
:抽象观察者(观察者的抽象类)它定义了一个更新接口,使得在得到主题更改通知时更新自己.
-
Concrereobserver
:具体观察者实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
UML图
- 具体被观察者 会通过
notify
方法通过遍历List
集合向其他对象发送值得关注的事件。 事件会在发布者自身状态改变或执行特定行为后发生。 发布者中包含一个允许新订阅者加入和当前订阅者离开列表的订阅构架。 - 观察者 接口声明了通知接口。 在绝大多数情况下, 该接口仅包含一个
update
更新方法。 该方法可以拥有多个参数, 使发布者能在更新时传递事件的详细信息。 - 具体观察者 可以执行一些操作来回应发布者的通知。 所有具体订阅者类都实现了同样的接口, 因此发布者不需要与具体类相耦合。
代码实现
1. 定义观察者接口
// 抽象观察者
public interface Observer {
void update(String message);
}
2. 定义主题接口
// 抽象主题角色类
public interface Subject {
// 添加订阅者(添加观察者对象)
void attach(Observer observer);
//删除订阅者
void detach(Observer observer);
//通知订阅者更新消息
void notify(String message);
}
3. 实现具体观察者
public class User implements Observer {
private String name;
public User(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + "接收到:" + message);
}
}
4. 实现具体被观察者
// 具体主题角色类
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);
}
}
}
5.测试
package com.feng.observer;
public class Client {
public static void main(String[] args) {
// 1.创建被观察者对象
SubscriptionSubject subject = new SubscriptionSubject();
// 2.创建用户对象
User user1 = new User("用户1");
User user2 = new User("用户2");
User user3 = new User("用户3");
// 3.进行订阅
subject.attach(user1);
subject.attach(user2);
subject.attach(user3);
// 4.被观察者发布
subject.notify("公众号更新了");
}
}
应用场景
- 当一个对象状态的改变需要改变其他对象,或实际对象是事先未知的或动态变化的时,可使用观察者模式。
- 当应用中的一些对象必须观察其他对象时,可使用该模式。但仅能在有限时间内或特定情况下使用。
优点
- 松耦合:观察者和主题之间是松耦合的。主题只知道观察者实现了一个特定的接口,观察者可以自由变化而不影响主题。
- 灵活性:可以在运行时添加或删除观察者,灵活应对需求的变化。
缺点
- 通知所有观察者的开销:如果观察者很多,通知所有观察者可能会很耗时。
- 可能导致循环依赖:如果两个对象互为观察者,可能会导致循环依赖和死循环。
感谢您的阅读
如有错误烦请指正
参考:
- 观察者设计模式 (refactoringguru.cn)
- 5.设计模式-行为型模式-观察者模式的概述_哔哩哔哩_bilibili