深度学习设计模式(二):基本的设计模式(例子+业务场景+八股)。
原文:CSDN(历史文章导入,当前状态为草稿)
基本设计模式
Section titled “基本设计模式”本篇的设计模式是基于框架去学习,所以顺序不分先后,挑自己需要的学习即可,还在持续更新,感兴趣可以关注一下后续。
行为型设计模式
Section titled “行为型设计模式”监视器模式也称为观察者或发布/订阅模式。
定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,当主题对象状态发生变化时,会通知所有的观察者对象,使它们自动更新自己。
基本概念包括以下几个方面:
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中运用到监视器模式的地方
Section titled “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带来的帮助。