观察者模式实战运用

本文介绍了观察者模式在Java中的应用,包括推模型和拉模型的区别,通过实例展示了如何使用Observable和Observer接口以及SpringEvent进行事件处理,以实现松耦合的业务逻辑设计。
摘要由CSDN通过智能技术生成

目录

前言

推模型

拉模型

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));
    }
}

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值