深度学习设计模式(二):基本的设计模式(例子+业务场景+八股)。

监视器模式是一种行为型设计模式,用于建立一种一对多的依赖关系,当一个对象的状态改变时,所有依赖于它的对象都会得到通知并自动更新。文章介绍了模式的基本概念,包括主题、观察者、具体主题和具体观察者等角色,并提供了Java实现示例。此外,还讨论了监视器模式在Spring框架中的应用,如事件驱动模型、SpringAOP和SpringMVC中的使用。
摘要由CSDN通过智能技术生成

前言

本篇的设计模式是基于框架去学习,所以顺序不分先后,挑自己需要的学习即可,还在持续更新,感兴趣可以关注一下后续。

行为型设计模式

监视器模式

基本概念

监视器模式也称为观察者或发布/订阅模式。
定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,当主题对象状态发生变化时,会通知所有的观察者对象,使它们自动更新自己。

基本概念包括以下几个方面:
1.主题(Subject):也成称为观察者模式(Observable),它是一个抽象类或接口,用于定义被观察者的基本属性和方法。主题对象包含一组观察者对象的引用,可以在状态发生变化时通知所有观察者对象。
2.观察者(Obserber):订阅者(Subscriber),它是一个抽象类或接口,用于定义观察者对象的基本属性和方法。观察者对象在被主题对象注册后,可以接受主题对象发出的通知,并进行相应的操作。
3.具体主题(Concrete Subject):实现主题或抽象类,它包含一个观察者对象的集合,提供注册,删除,通知等操作,当主题对象状态发生变化时,会通知所有观察者对象。
4.具体观察者(Concrete Observer):实现观察者接口或抽象类,它存储一个指向具体主题对象的引用,在接受到主题对象的通知后,执行相应的操作,使自身状态与主题对象保持同步。
5.通知(Notification):主题对象状态发生变化时,通过调用观察者对象的通知方法来通知观察者对象。
6.订阅(Subscription):观察者对象通过注册方法向主题对象注册,将自身添加到主题对象的观察者列表中。
7.取消订阅(Unsubscription):观察者对象通过删除方法从主题对象的观察者列表中删除自身。

适用场景:
1.一个对象改变需要同时改变其他对象的时候。
业务场景:在一个电商网站中,当用户下单购买商品后,需要通知库存管
2.一个对象的改变会触发连锁反应的时候。
业务场景:游戏中,当玩家升级时,需要通知任务系统判断是否完成了某些任务、通知好友系统向好友发送升级通知等。
3.一个对象需要将自身的状态通知给其他对象的时候。
业务场景:在一个股票交易系统中,当股票价格变化时,需要通知投资者进行交易操作。
4.一个对象需要在不同时间通知不同对象的时候。
业务场景:在一个消息推送系统中,需要根据不同的订阅主题向不同的用户推送消息。

总而言之:监视器模式适用于当多个对象之间的状态存在依赖关系,需要实现一对多的消息通知机制时。

实现方式

1.使用Java内置的观察者(Observer)接口和可观察者(Observable)类实现。
Observer接口表示观察者,Observable类表示被观察者。
被观察者状态发生变化时,通过调用被观察者类的notifyObservers()方法来通知所有的观察者对象。
这种方式实现了一个标准吧的监视器模式,但要注意:Java中的Observable类是一个类而不是接口,所以不能直接继承它,需要通过继承Observable类的子类来实现。

举个例子来看:

import java.util.Observable;
import java.util.Observer;

// 定义一个被观察者类
class WeatherData extends Observable {
    private float temperature;
    private float humidity;
    private float pressure;

    public void measurementsChanged() {
        setChanged();  // 标记状态已经改变
        notifyObservers();  // 通知所有观察者
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();  // 触发状态改变事件
    }

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }
}

// 定义一个观察者接口
interface Observer {
    void update(Observable observable, Object arg);
}

// 定义一个具体观察者类
class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;

    public void update(Observable observable, Object arg) {
        if (observable instanceof WeatherData) {
            WeatherData weatherData = (WeatherData) observable;
            this.temperature = weatherData.getTemperature();
            this.humidity = weatherData.getHumidity();
            display();
        }
    }

    public void display() {
        System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
    }
}

// 测试代码
public class Test {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
        weatherData.addObserver(currentDisplay);  // 添加观察者

        weatherData.setMeasurements(80, 65, 30.4f);
    }
}

WeatherData类表示被观察者,CurrentConditionsDisplay类表示观察者。
当WeatherData对象的状态发生改变时,会通过调用Observable类的setChanged()方法来标记状态已经改变,然后通过调用notifyObservers()方法来通知所有的观察者对象。当观察者对象收到通知后,会调用update()方法来更新自身状态。

2.自己实现观察者和被观察者接口。
定义一个抽象的主题(Subject)类和抽象的观察者(Observer)类,具体主题和观察者则通过继承抽象类来实现。
当主题对象状态发生变化时,通知所有观察者对象,并调用观察者对象的更新方法(update())。
举个例子来看:

import java.util.ArrayList;
import java.util.List;
// 观察者接口
interface Observer {
    void update(int value);
}
// 被观察者接口
interface Observable {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}
// 被观察者的实现
class MyObservable implements Observable {
    private List<Observer> observers = new ArrayList<>();
    private int value = 0;
    @Override
    public void addObserver(Observer observer) {
        observers.add(observer);
    }
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(value);
        }
    }
    // 设置值,并通知所有观察者
    public void setValue(int value) {
        this.value = value;
        notifyObservers();
    }
}
// 观察者的实现
class MyObserver implements Observer {
    @Override
    public void update(int value) {
        System.out.println("Value is updated to " + value);
    }
}
// 测试代码
public class Main {
    public static void main(String[] args) {
        MyObservable observable = new MyObservable();
        MyObserver observer = new MyObserver();
        observable.addObserver(observer); // 添加观察者
        observable.setValue(10); // 修改值,并通知观察者
        observable.setValue(20); // 修改值,并通知观察者
        observable.removeObserver(observer); // 移除观察者
        observable.setValue(30); // 修改值,但不通知观察者
    }
}

我们自己定义了 Observer 和 Observable 接口,分别表示观察者和被观察者。

  • MyObservable 类实现了 Observable 接口,并维护了一个观察者列表和一个整型值。
    addObserver 方法用于添加观察者,removeObserver 方法用于移除观察者,notifyObservers 方法用于通知所有观察者。setValue 方法用于修改整型值,并在修改后调用 notifyObservers 方法通知所有观察者。
  • MyObserver 类实现了 Observer 接口。
    实现了 update 方法,用于在被观察者发生改变时更新状态。在 Main 类中,我们创建了一个被观察者和一个观察者,然后测试了添加、移除和通知观察者的功能。

3.使用Java内置的事件(Event)类实现。
事件类(Event)是一个基类,可以定义多个派生类,用于表示不同的事件。
事件源(Event Source)负责产生事件,并且在事件发生时通知所有的事件监听器(Event Listener)。
事件监听器(Event Listener)则负责处理事件,并且可以将处理结果通知给事件源或其他对象。

举个例子来看:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;

// 观察者类
class MyObserver implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Button is clicked");
    }
}

// 测试代码
public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JButton button = new JButton("Click me");
        button.addActionListener(new MyObserver()); // 添加观察者
        frame.add(button);
        frame.pack();
        frame.setVisible(true);
    }
}

我们使用了 Java 内置的 ActionListener 接口作为观察者接口,JButton 类作为被观察者。
MyObserver 类实现了 ActionListener 接口,在按钮被点击时会触发 actionPerformed 方法。
在 Main 类中,我们创建了一个窗口和一个按钮,将 MyObserver 对象作为按钮的监听器,当按钮被点击时就会通知观察者并执行相应的操作。

4.使用回调函数(Callback)实现。
定义观察者接口和被观察者类,观察者需要实现观察者接口中的方法,并将自己的方法作为参数传递给被观察者。
当被观察者发生变化时,会调用观察者的方法,执行相应的操作。

举个例子来看:

// 观察者接口
interface Observer {
    void onUpdate(String message);
}

// 被观察者类
class Observable {
    private Observer observer;

    // 设置观察者对象
    public void setObserver(Observer observer) {
        this.observer = observer;
    }

    // 模拟事件发生,通知观察者
    public void eventHappened() {
        if (observer != null) {
            observer.onUpdate("Event happened");
        }
    }
}

// 测试代码
public class Main {
    public static void main(String[] args) {
        Observable observable = new Observable();

        // 使用Lambda表达式作为回调函数,实现Observer接口
        Observer observer = (message) -> {
            System.out.println("Received message: " + message);
        };

        // 设置观察者对象
        observable.setObserver(observer);

        // 模拟事件发生
        observable.eventHappened();
    }
}

定义了一个观察者接口 Observer,它包含一个 onUpdate 方法,表示观察者在接收到通知后需要执行的操作。
被观察者类 Observable 中包含一个 Observer 类型的成员变量 observer,它表示观察者对象。
Observable 类中的 eventHappened 方法模拟一个事件的发生,当事件发生时,被观察者会通知观察者执行相应的操作。
测试代码中,我们使用 Lambda 表达式作为回调函数,实现了 Observer 接口,并将它作为参数传递给 Observable 对象的 setObserver 方法。
当事件发生时,观察者对象就会收到通知,并执行相应的操作。

Spring中运用到监视器模式的地方

这个等我更新完refresh后再来填坑。
目前三个常见的适用场景:
1.Spring事件驱动模型:
Spring框架使用了事件(Event)和监听器(Listener)的机制,实现了一种事件驱动的模型。Spring中的事件(Event)通常是一个POJO(Plain Old Java Object)对象,而监听器(Listener)是一个实现了特定接口的POJO对象。当事件被触发时,Spring会通知所有注册了相应监听器的对象,让它们执行相应的操作。
2.Spring AOP(面向切面编程):
Spring AOP中的切面就是一个特殊的监听器,它可以监听被通知对象(即目标对象)的方法调用,并在相应的时机执行一些操作。
3.Spring MVC(模型-视图-控制器):
Spring MVC中的控制器(Controller)通常是一个Servlet或者一个POJO,它可以接收HTTP请求并处理相应的业务逻辑。当一个请求被发送到控制器时,Spring会触发一个事件,并通知所有注册了相应监听器的对象。这些监听器可以对请求进行一些预处理或者后处理,比如记录请求日志、检查权限等。

后面我们更深入的去赏析监听器模式给spring带来的帮助。

待填坑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值