今天发现微信被拉黑了,哈哈哈哈哈哈。除了代码一无所有
行为型模式之:
-
职责链模式(Chain of Responsibility)
重要程度:⭐️⭐️⭐️ -
命令模式(Command)
重要程度:⭐️⭐️⭐️⭐️ -
解释器模式(Interpreter)
重要程度:⭐️ -
迭代器模式(Iterator)
重要程度:⭐️⭐️⭐️⭐️⭐️ -
中介者模式(Mediator)
重要程度:⭐️⭐️ -
备忘录模式(Memento)
重要程度:⭐️⭐️ -
观察者模式(Observer)
重要程度:⭐️⭐️⭐️⭐️⭐️ -
状态模式(State)
重要程度:⭐️⭐️⭐️ -
策略模式(Strategy)
重要程度:⭐️⭐️⭐️⭐️ -
模板方法模式(Template Method)
重要程度:⭐️⭐️⭐️ -
访问者模式(Visitor)
重要程度:⭐️
前面学习了解决“对象的创建”的创建型设计模式,解决“类或对象的组合或组装”结构型设计模式,今天学习最后一类设计模式,解决“类或对象之间的交互”问题的行为型设计模式。
从上面的列举中可以看出,最重要的或者说最常使用的设计模式主要是观察者模式、迭代器模式;命令模式和策略模式次之,职责链模式、状态模式和模版模式位于最后。
今天主要学习观察者模式,我一个同事说,设计模式他主要是使用的就是观察者模式。特别是eventBus就是观察者模式的主要体现和常用框架。
1.什么是观察者模式
观察者模式也叫订阅者模式。 它定义了一种一对多的关系,当一个对象的状态发生变化时,所有依赖它的对象都会得到通知并自动更新。 顾名思义和我们订阅报纸一样,一个小区有100户人家,只有1家订阅了报纸,送报员每天早晨都会送到,没有定报纸的99户人家不会受到任何影响。 举一个简单的例子来说明观察者模式:
假设有一个天气数据系统,用户可以订阅天气数据并随时获取最新的天气信息。
- 观察者(Observer):用户就是观察者,他们希望在天气数据更新时得到通知并获取最新的天气信息。
- 被观察者(Subject):天气数据系统是被观察者,它负责收集和更新天气信息,并在数据更新时通知所有的观察者。
注意。观察者模式是通知想要获取到信息的用户,不想获取信息的用户是没有必要去实现的,提取下观察者模式的思想:
- 1:想要获取的用户,首先要成为订阅者。
- 2:订阅想要获取的内容。
- 3:移除不想订阅的内容(订阅者5)
2.观察者模式的实现
// 观察者接口
interface Observer {
void update(String weather);
}
// 被观察者接口
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具体的观察者实现类
class User implements Observer {
private String name;
public User(String name) {
this.name = name;
}
@Override
public void update(String weather) {
System.out.println(name + "收到最新的天气信息:" + weather);
}
}
// 具体的被观察者实现类
class WeatherData implements Subject {
private List<Observer> observers = new ArrayList<>();
private String weather;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(weather);
}
}
// 当天气更新时调用该方法
public void setWeather(String weather) {
this.weather = weather;
notifyObservers(); // 通知所有观察者
}
}
// 测试代码
public class Main {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
// 创建观察者并注册到被观察者中
Observer user1 = new User("User1");
Observer user2 = new User("User2");
weatherData.registerObserver(user1);
weatherData.registerObserver(user2);
// 模拟天气更新
weatherData.setWeather("晴天");
weatherData.setWeather("阴天");
}
}
在上面的示例中,User类是观察者,它实现了Observer接口;WeatherData类是被观察者,它实现了Subject接口。当WeatherData的天气更新时,会通知所有注册的观察者,观察者会收到最新的天气信息并做出相应的处理。
3.观察者模式的选择场景
想要监听获取对象的状态变化&&通知对象我方的状态变化
- 当一个对象的状态发生变化需要通知其他对象,并且不确定这些对象是谁。
- 当一个对象需要在改变时通知其他对象,但又不希望这些对象是紧密耦合的。
- 当一个对象的改变需要其他对象采取一系列的动作,但不清楚有多少对象需要采取这些动作。
- 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这两个方面分离开来可能会更好。
4.观察者模式的实际使用
- Android系统中的LiveData: LiveData是一种可观察的数据持有类,在数据发生变化时通知观察者。它常用于在Android应用程序中管理UI组件的数据,并确保UI组件在数据变化时及时更新。
- Java Swing和JavaFX中的事件处理机制: 在Java Swing和JavaFX中,观察者模式用于处理用户界面事件。事件源(如按钮、文本框等)充当被观察者,而事件监听器则充当观察者,监听器会在事件发生时接收通知并执行相应的操作。
- RxJava: RxJava是一个在Java平台上实现的响应式编程库,它使用观察者模式来支持响应式编程范式。在RxJava中,被观察者(Observable)可以发出事件,而观察者(Observer)则订阅这些事件,并在事件发生时做出响应。
- Spring Framework中的事件机制: Spring框架提供了一个事件机制,允许应用程序内的组件通过发布事件来通知其他组件。事件源是应用程序中的任何对象,它可以发布事件并将其传递给已注册的监听器(观察者)。
当然,这里以eventBus为例。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class EventBus {
private static EventBus instance;
private Map<Class<?>, List<Subscriber>> subscribers;
private EventBus() {
subscribers = new HashMap<>();
}
public static EventBus getInstance() {
if (instance == null) {
synchronized (EventBus.class) {
if (instance == null) {
instance = new EventBus();
}
}
}
return instance;
}
public void register(Object subscriber) {
for (Map.Entry<Class<?>, List<Subscriber>> entry : subscribers.entrySet()) {
if (entry.getKey().isAssignableFrom(subscriber.getClass())) {
entry.getValue().add(new Subscriber(subscriber));
}
}
}
public void post(Object event) {
Class<?> eventClass = event.getClass();
for (Map.Entry<Class<?>, List<Subscriber>> entry : subscribers.entrySet()) {
if (entry.getKey().isAssignableFrom(eventClass)) {
for (Subscriber subscriber : entry.getValue()) {
subscriber.handleEvent(event);
}
}
}
}
public void unregister(Object subscriber) {
for (List<Subscriber> subscriberList : subscribers.values()) {
for (Subscriber sub : subscriberList) {
if (sub.getSubscriber() == subscriber) {
subscriberList.remove(sub);
break;
}
}
}
}
private static class Subscriber {
private Object subscriber;
public Subscriber(Object subscriber) {
this.subscriber = subscriber;
}
public Object getSubscriber() {
return subscriber;
}
public void handleEvent(Object event) {
// Handle the event
}
}
}
EventBus是单例模式,通过getInstance()方法获取实例。register(Object subscriber)方法用于注册订阅者,将订阅者与相应的事件类型关联起来。post(Object event)方法用于发布事件,当有事件发生时,EventBus会将事件传递给所有订阅者。unregister(Object subscriber)方法用于取消注册订阅者,避免内存泄漏。
在实际的EventBus库中,还包括了更多功能,如事件的线程调度、粘性事件支持等。以上代码仅展示了EventBus的基本原理和简化实现。EventBus详细的文章可以看这个链接,很细juejin.cn/post/684490…
5.观察者模式的优缺点
优点:
- 开闭原则。 你无需修改发布者代码就能引入新的订阅者类 (如果是发布者接口则可轻松引入发布者类)。
- 你可以在运行时建立对象之间的联系。
缺点:
- 引起内存泄漏: 如果观察者没有被正确地取消注册,就有可能引起内存泄漏问题,因为被观察者保留了对观察者的引用。
- 通知顺序不确定: 观察者模式中,观察者的调用顺序是不确定的,可能会导致意外的结果,需要在设计上进行合理的考虑和规划。
- 可能导致性能问题: 如果被观察者对象有大量的观察者,并且频繁地状态变化,可能会导致性能问题,因为每次状态变化都需要通知所有的观察者。