目录

前言

推模型

拉模型

UML

plantuml

类图

实战代码

观察者模板

Observable

Observer

Client

Spring Event

Event

EventListener

Client


前言

使用观察者模式,便能够在对象之间建立起一种一对多(主题与观察者)的依赖关系,当主题对象改变状态时,所有依赖它的观察者对象都会得到通知并且自动更新。

通过主题对象来使客户端与观察者对象之间的通信更加松散耦合、灵活可扩展。

一般用来解耦不同的业务逻辑,比如将实时更新、动态同步等功能与其它业务逻辑解耦。

可分为两种模式:推模型和拉模型

推模型

主题对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。

拉模型

主题对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到主题对象中获取,相当于是观察者从主题对象中拉数据。一般这种模型的实现中,会把主题对象自身通过update()方法传递给观察者,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了。

UML

plantuml

@startuml
'https://plantuml.com/class-diagram

interface Subject {
    + add(Observer) : void
    + remove(int) : void
    + notify() : void
}

class ConcreteSubject {
    - Observers : List<Observer>
    + add(Observer) : void
    + remove(int) : void
    + notify() : void
}

interface Observer {
    + update(Subject) : void
}

class ConcreteObserver {
    - field : type
    + update(Subject) : void
}

Subject <|.. ConcreteSubject
Observer <|.. ConcreteObserver

Subject "1" --> "n" Observer
Observer ..> Subject

@enduml

类图

实战代码

观察者模板

基于 JDK 的 Observable 和 Observer 接口 实现推模型观察者模式

Observable

public class CurrentTimeObservable extends Observable {

    int hour;

    public void updateHour() {
        Calendar now = Calendar.getInstance();
        this.hour = now.get(Calendar.HOUR_OF_DAY);
        System.out.println("current hour: " + this.hour);
    }

    public void startNotify() {
        setChanged();
        notifyObservers(hour);
    }
}

Observer

public class PeopleObserver implements Observer {
    String name;
    Map<Integer, String> schedule;

    PeopleObserver(String name, Map<Integer, String> sourceMap) {
        this.name = name;
        schedule = new TreeMap<>(Comparator.comparingInt(o -> o));
        schedule.putAll(sourceMap);
    }

    @Override
    public void update(Observable o, Object arg) {
        int hour = (int) arg;

        String action = Optional.ofNullable(schedule.get(hour)).orElseGet(() ->
            schedule.entrySet().stream()
                    .min((e1, e2) -> Math.abs(e1.getKey() - hour) <= Math.abs(e2.getKey() - hour) ? -1 : 1)
                    .get().getValue());

        System.out.println(String.format("%s %s", name, action));
    }
}

Client

public class Client {

    public static void main(String[] args) {
        Map<Integer, String> scheduleA = new HashMap<>();
        scheduleA.put(8, "sleep");
        scheduleA.put(9, "wake up");
        scheduleA.put(12, "eat");
        scheduleA.put(13, "work");
        scheduleA.put(20, "study");
        PeopleObserver people1 = new PeopleObserver("mike", scheduleA);

        Map<Integer, String> scheduleB = new HashMap<>();
        scheduleB.put(7, "sleep");
        scheduleB.put(8, "wake up");
        scheduleB.put(11, "eat");
        scheduleB.put(12, "play");
        PeopleObserver people2 = new PeopleObserver("tom", scheduleB);

        CurrentTimeObservable currentTimeObservable = new CurrentTimeObservable();
        currentTimeObservable.addObserver(people1);
        currentTimeObservable.addObserver(people2);
        currentTimeObservable.updateHour();
        currentTimeObservable.startNotify();
    }
}

Spring Event

Spring Event 是 Spring 框架的事件处理机制,建立在观察者模式的基础上,允许不同组件之间通过事件来通信,事件发送者通过容器发送事件,事件监听器负责监特定类型的事件,并执行事件触发时业务逻辑。

使用 Event 可以用来解耦业务逻辑,无需直接引用,事件发布者和事件监听者各自独立变化,不会互相影响,程序更加灵活和可扩展。

Event

public class MyEvent extends ApplicationEvent {
    public MyEvent(Object source) {
        super(source);
    }
}

EventListener

@Component
public class MyEventListener {

    @EventListener(MyEvent.class)
    public void onApplicationEvent(MyEvent event) {
        System.out.println("EventListener::onApplicationEvent");
    }
}

Client

@Component
public class MyService {

    @Autowired
    ApplicationContext applicationContext;

    public void dealBiz()
    {
        //业务逻辑处理
            
        //发送事件
        applicationContext.publishEvent(new MyEvent(null));
    }
}

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐