探索设计模式的魅力:捕捉变化的风-用观察者模式提升用户体验


设计模式专栏:http://t.csdnimg.cn/U54zu


目录

一、引言

 核心概念

 应用场景

 可以解决的问题

二、场景案例

2.1 不用设计模式实现

2.2 存在问题

2.3 使用设计模式实现

2.4 成功克服

三、工作原理

3.1 结构图和说明

3.2 工作原理详解

3.3 实现步骤

四、 优势

4.1 好处和优势

4.2 应用示例

4.3 系统性优势

五、局限性和注意事项

5.1 局限性与不适用的场景

5.2 实际应用中的注意事项与建议


一、引言

 核心概念

    优雅方案

  • 在现代软件开发中,我们经常面临着如何实现不同组件之间的高效通信动态响应的问题。而观察者模式就是一个重要的设计模式,它提供了一种 elegant 的解决方案。

    观察者模式的核心概念主要包含以下几个关键部分:

 1. 主题(Subject)

  • 也称为被观察者或发布者,是核心组件之一。主题拥有维护一系列观察者的能力,提供注册(添加)和注销(移除)观察者的接口。当主题对象的状态发生变化时,它负责通知所有注册的观察者。

 2. 观察者(Observer)

  • 是一个接口或抽象类,规定了当主题的状态发生变化时应该执行的更新操作。具体观察者实现该接口,定义了在接收到主题状态变化通知时的具体行为。

 3. 具体主题(Concrete Subject)

  • 实现或继承主题接口的类。维护观察者的列表,并实现通知观察者的具体逻辑。

 4. 具体观察者(Concrete Observer)

  • 实现或继承观察者接口的类。当接收到主题的状态变化通知时,具体观察者会按定义的逻辑进行更新或其他响应。

 5. 状态(State)

  • 就是主题对象维护的、观察者感兴趣的数据。当状态发生变化时,主题会触发一个通知流程来更新所有的观察者。

 6. 更新接口(Update Method)

  • 是观察者定义的方法,在被主题通知时被调用用以更新自身状态。

  简单而言

    观察者模式允许对象之间建立一种一对多的依赖关系,当一个对象改变状态时,所有依赖它的对象都会得到通知并且自动更新。这种通知机制使得对象之间的通信更加松散耦合、灵活可扩展。无需直接相互引用,各个对象能够独立变化而互不影响。通过观察者模式,我们能够轻松实现实时更新、动态同步等功能,从而为我们的应用带来更好的用户体验和可维护性。无论是构建响应式界面、事件驱动系统,还是实现即时通信、发布-订阅模式,观察者模式都是一个不可或缺的设计选择。

    接下来,让我们深入探索观察者模式的内部工作原理和实际应用案例,享受软件开发的乐趣吧! 

 应用场景

  观察者模式在软件设计中的应用场景

 1. 用户界面(UI)交互

  • 当用户操作引发状态变化,比如一个按钮点击导致数据更新,观察者模式确保相关UI组件同步刷新。

 2. 事件监测系统

  • 系统中的某些事件发生时,如文件下载完成或硬件状态变更,观察者模式通知所有订阅者执行适当的动作。

 3. 发布/订阅系统

  • 在消息队列或实时消息服务中,产生消息的发布者与消费消息的订阅者无需知晓对方的存在。

 4. 数据模型与视图同步

  • 在MVC架构中,数据模型的更改需要能够实时地反映到视图上,观察者模式在此场景下保持视图和数据的一致性。

 可以解决的问题

    在现代软件开发中,组件间的交互和状态同步是一项常见而又至关重要的挑战。随着业务逻辑的复杂化及用户需求的不断变化,如何设计出灵活、低耦合的系统成为软件工程师面临的一大课题。对于系统中存在的一个实体状态改变需要通知到一个或多个依赖该状态的实体的场景,如何高效率地处理这种状态同步与通知呢?传统的紧耦合联系很难应对系统的迅速变化和扩展,而观察者模式在此场景下应运而生,提供了一种优雅且实用的设计解决方案。

  使用观察者模式可以解决的问题包括但不限于

  1. 解耦系统组件:降低对象之间的直接交互,实现松耦合,从而改善组件间的交互模式。
  2. 实现广播通信:当我们希望状态的改变能够通知到所有相关的依赖者而不是单一对象时,观察者模式提供了有效的机制。
  3. 动态交互:允许系统在运行时动态地新增或移除观察者,无需修改主题或其他观察者的代码。
  4. 推拉模型的支持:提供了推模型(主题向观察者推送详细信息)和拉模型(观察者自行获取其所需要的信息)两种方式。

        

二、场景案例

 经典场景:新闻发布系统

    最经典的观察者模式场景之一是“新闻发布系统”。在这个场景中,有多个订阅者(观察者)对新闻感兴趣,他们希望在有新闻发布时能够立即得到通知。系统管理员(主题)负责发布新闻。

2.1 不用设计模式实现

 一坨坨代码实现

import java.util.ArrayList;  
import java.util.List;  // 新闻类  
class News {  private String content;  public News(String content) {  this.content = content;  }  public String getContent() {  return content;  }  
}  // 新闻发布器  
class NewsPublisher {  private List<NewsSubscriber> subscribers = new ArrayList<>();  // 订阅新闻  public void subscribe(NewsSubscriber subscriber) {  subscribers.add(subscriber);  }  // 取消订阅  public void unsubscribe(NewsSubscriber subscriber) {  subscribers.remove(subscriber);  }  // 发布新闻  public void publish(News news) {  for (NewsSubscriber subscriber : subscribers) {  subscriber.receiveNews(news);  }  }  
}  // 新闻订阅者接口  
interface NewsSubscriber {  void receiveNews(News news);  
}  // 网页新闻订阅者  
class WebNewsSubscriber implements NewsSubscriber {  @Override  public void receiveNews(News news) {  System.out.println("WebNewsSubscriber: News received - " + news.getContent());  }  
}  // 邮件新闻订阅者  
class EmailNewsSubscriber implements NewsSubscriber {  @Override  public void receiveNews(News news) {  System.out.println("EmailNewsSubscriber: News received - " + news.getContent());  }  
}  // 客户端代码  
public class NewsSystemClient {  public static void main(String[] args) {  NewsPublisher publisher = new NewsPublisher();  NewsSubscriber webSubscriber = new WebNewsSubscriber();  NewsSubscriber emailSubscriber = new EmailNewsSubscriber();  publisher.subscribe(webSubscriber);  publisher.subscribe(emailSubscriber);  News news = new News("Breaking News: World Peace Achieved!");  publisher.publish(news);  }  
}

    在这个实现中,NewsPublisher 类充当了新闻发布的中心角色,它维护了一个订阅者列表。当有新闻发布时,NewsPublisher 会遍历订阅者列表,并调用每个订阅者的 receiveNews 方法来传递新闻。 

2.2 存在问题

    上述不使用设计模式实现的新闻发布系统确实存在一些问题,尽管它能够实现基本的新闻发布和接收功能。以下还是存在如紧耦合缺乏灵活性可扩展性差错误处理不足缺乏抽象层次 动态性受限 等问题。

2.3 使用设计模式实现

 1. 观察者接口(Observer):定义一个更新方法,当新闻发布时,所有观察者都将调用此方法。

public interface Observer {  void update(String news);  
}

 2. 具体观察者(ConcreteObserver):实现观察者接口,当有新闻发布时,执行具体的操作。例如,将新闻显示在网页上、发送到用户的电子邮箱等。

public class WebObserver implements Observer {  @Override  public void update(String news) {  System.out.println("WebObserver: Display news on website - " + news);  }  
}  public class EmailObserver implements Observer {  @Override  public void update(String news) {  System.out.println("EmailObserver: Send news to email - " + news);  }  
}

 3. 主题接口(Subject):定义一个注册观察者、移除观察者和通知观察者的方法。

import java.util.ArrayList;  
import java.util.List;  public interface Subject {  void registerObserver(Observer observer);  void removeObserver(Observer observer);  void notifyObservers(String news);  
}

 4. 具体主题(ConcreteSubject):实现主题接口,维护一个观察者列表,并在有新闻发布时通知所有观察者。

public class NewsSubject implements Subject {  private List<Observer> observers = new ArrayList<>();  @Override  public void registerObserver(Observer observer) {  observers.add(observer);  }  @Override  public void removeObserver(Observer observer) {  observers.remove(observer);  }  @Override  public void notifyObservers(String news) {  for (Observer observer : observers) {  observer.update(news);  }  }  
}

 5. 客户端代码(Client):创建主题和观察者对象,并将观察者注册到主题上。当有新闻发布时,主题会通知所有观察者。

public class Client {  public static void main(String[] args) {  NewsSubject newsSubject = new NewsSubject();  Observer webObserver = new WebObserver();  Observer emailObserver = new EmailObserver();  newsSubject.registerObserver(webObserver);  newsSubject.registerObserver(emailObserver);  newsSubject.notifyObservers("Breaking News: World Peace Achieved!");  }  
}

    在这个场景中,新闻发布系统(主题)负责发布新闻,而网页观察者(WebObserver)和电子邮件观察者(EmailObserver)则负责在新闻发布时显示和发送新闻。通过使用观察者模式,系统管理员可以轻松地添加或移除观察者,而无需修改主题代码。此外,当有新闻发布时,所有观察者都会自动收到通知并更新,从而实现了松耦合和可扩展性。 

2.4 成功克服

    使用观察者模式在上述示例中成功克服了多个问题,这些问题在使用直接的方法调用和对象间显式交互时可能会出现。以下是观察者模式成功克服的问题:

 1. 紧耦合

  • 观察者模式通过引入抽象和接口,降低了新闻发布器(主题)和订阅者(观察者)之间的耦合度。这意味着如果新闻发布器的内部实现发生变化,只要它继续遵循观察者模式的接口,订阅者的代码就不需要修改。

 2. 缺乏灵活性

  • 观察者模式允许主题和观察者之间的解耦,从而提高了系统的灵活性。这意味着可以更容易地支持多种不同的订阅场景,比如特定的时间间隔接收新闻或只接收特定类型的新闻。

 3. 可扩展性差

  • 通过引入抽象和接口,观察者模式允许更容易地扩展系统。例如,可以轻松地添加新的观察者类型,而不需要修改现有的代码。此外,由于观察者模式的通知机制是异步的,它也可以更好地处理大量观察者的情况,避免性能问题。

 4. 错误处理不足

  • 观察者模式允许在观察者中实现错误处理逻辑。这意味着如果某个订阅者在接收新闻时出现问题,它可以优雅地处理这些错误,而不会影响到新闻发布器或其他订阅者。

 5. 缺乏抽象层次

  • 观察者模式通过引入抽象和接口,为系统提供了更好的抽象层次。这使得系统更易于进行单元测试和维护,因为可以针对抽象接口编写测试,而不是针对具体的实现。

 6. 动态性受限

  • 观察者模式允许观察者在运行时动态地注册和注销,从而提高了系统的动态性。这意味着可以更容易地支持动态添加或删除订阅者的需求。

        

三、工作原理

3.1 结构图和说明

  • Subject:目标对象,通常具有如下功能。
  • Observer:定义观察者的接又,提供目标通知时对应的更新方法,这个更新方法进行相应的业务处理,可以在这个方法里面回调目标对象,以获取目标对象的数据。
  • ConcreteSubject:具体的目标实现对象,用来维护目标状态,当目标对象的状态发生改变时,通知所有注册的、有效的观察者,让观察者执行相应的处理

  • ConcreteObserver:观察者的具体实现对象,用来接收目标的通知,并进行相应的后续处理,比如更新自身的状态以保持和目标的相应状态一致。

3.2 工作原理详解

 1. 注册与订阅

  • 首先,观察者需要向被观察者注册或订阅感兴趣的事件或主题。这通常是通过调用被观察者的某个注册方法来实现的,该方法将观察者添加到其内部维护的观察者列表中。

 2. 状态变化

  • 当被观察者的状态发生变化时,它会通知所有已注册的观察者。这通常是通过调用一个通知方法来实现的,该方法遍历观察者列表并调用每个观察者的更新方法。

 3. 通知更新

  • 观察者接收到通知后,会根据自己的需要执行相应的操作或更新自己的状态。这通常是通过实现一个更新方法来完成的,该方法在被调用时会根据被观察者的新状态进行相应的处理。

 4. 解耦

  • 观察者模式的核心优势在于它实现了观察者和被观察者之间的解耦。被观察者不需要知道具体的观察者是谁,也不需要关心观察者如何响应状态变化。同样,观察者也不需要知道被观察者的具体实现细节,只需要关心自己感兴趣的事件或主题。

 5. 灵活性和扩展性

  • 由于观察者和被观察者之间的解耦关系,我们可以在不修改现有代码的情况下添加新的观察者或更改观察者的行为。这为软件系统的灵活性和扩展性提供了很好的支持。

3.3 实现步骤

    使用观察者模式实现功能时,你可以按照以下思考步骤进行:

 1. 定义主题和观察者之间的关系

  • 确定哪个对象应当作为主题,即数据变化的源头。
  • 识别哪些对象应当作为观察者,即需要响应数据变化的对象。
  • 设计一种方式让观察者能够订阅并从主题接收更新。

 2. 设计通用接口

  • 为观察者定义统一的接口,以便主题更新数据时能够通知所有观察者。
  • 考虑定义主题接口,描述如何注册、注销观察者,以及怎样发出通知。

 3. 实现注册与移除观察者功能

  • 主题需要提供方法让观察者能够注册自己或者被移除。
  • 主题内部需要有机制跟踪所有注册的观察者。

 4. 定义通知机制

  • 确定更新状态后观察者被通知的机制是推送还是拉取。
  • 设计主题在状态更改时如何通知观察者的逻辑。

 5. 更新观察者状态

  • 观察者接口中应定义如何更新其状态以响应主题状态变化的方法。
  • 实现观察者根据接收到的更新来进行自身状态更改或相应行为的逻辑。

 6. 考虑线程安全与性能问题

  • 如果在多线程环境下,确保主题在通知观察者时的线程安全性。
  • 分析性能问题,确保通知机制不会成为瓶颈。

 7. 实现解耦

  • 观察者和主题应该保持松耦合,以便独立变化而不影响彼此。

 8. 处理异常与错误

  • 确保即便某个观察者处理失败,也不应影响到主题和其他观察者。

 9. 测试

  • 对主题、观察者以及整个通知机制进行测试,确保满足需求。
  • 验证在增加或删除观察者、变更主题状态时,系统行为正确无误。

 10. 细节优化

  • 根据反馈和测试结果优化设计,可能涉及提高性能、简化接口、增强用户体验等。

     在应用观察者模式时,始终需要关注设计的整体清晰度、灵活性以及扩展性,确保最终实现的模式适合应用的上下文环境。

        

四、 优势

4.1 好处和优势

    使用观察者模式可以带来以下明显的好处和优势:

 1. 解耦

  • 观察者模式实现了观察者和被观察者之间的解耦,这意味着两者之间的依赖关系变得更加松散。这种解耦关系有助于提高代码的可维护性和可重用性,因为你可以在不修改被观察者代码的情况下添加或删除观察者。

 2. 灵活性

  • 由于观察者和被观察者之间的解耦关系,你可以灵活地添加、删除或更改观察者,而无需修改被观察者的代码。这为系统的扩展和修改提供了极大的便利。

 3. 动态响应

  • 观察者模式允许被观察者在其状态发生变化时自动通知所有相关的观察者。这种动态响应机制使得系统能够实时地响应变化,从而提高了系统的响应速度和效率。

 4. 简化通信

  • 观察者模式提供了一种简洁而有效的方式来处理不同组件之间的通信。通过观察者和被观察者之间的注册、通知和更新机制,你可以轻松地实现组件之间的通信和协作。

4.2 应用示例

    考虑一个电商平台上的商品定价系统。传统的设计方法可能会要求每个依赖商品价格信息的组件都直接从价格数据库中获取更新。随着系统的发展,这种紧耦合的方式导致了若干问题:每当价格更新逻辑变化时,所有依赖组件都需要作出相应修改;系统的可扩展性差,添加新的依赖组件会带来额外的维护负担。
    采用观察者模式改进后,价格系统作为主题,各个依赖组件(如库存管理、促销引擎、前端显示等)作为观察者。当商品价格更新时,价格系统仅需通知这些观察者。这样,库存管理系统可以自动调整库存采购策略,促销引擎可以同步更新促销活动,用户界面也可以即时显示最新价格。这种方式不仅使得价格更新流程更加清晰,而且让各组件能够更加独立地开发和维护。

4.3 系统性优势

    观察者模式通过解耦观察者和被观察者之间的关系,提高了系统的灵活性、扩展性和可维护性。具体来说:

 1. 灵活性

  • 由于观察者和被观察者之间的解耦关系,你可以在不修改现有代码的情况下添加新的观察者或更改观察者的行为。这为系统的灵活性提供了很好的支持。

 2. 扩展性

  • 观察者模式允许你轻松地扩展系统的功能。例如,你可以添加新的观察者来处理新的事件或主题,而无需修改现有的代码。这种扩展性使得系统能够适应不断变化的需求。

 3. 可维护性

  • 由于观察者模式降低了对象之间的耦合度,代码变得更加清晰和易于维护。当一个对象的状态发生变化时,你只需要修改被观察者的代码,而无需关心与之相关的多个对象的代码。这大大降低了维护成本和出错的可能性。

    综上所述,观察者模式通过解耦观察者和被观察者之间的关系,提高了系统的灵活性、扩展性和可维护性。它简化了对象之间的通信和协作,使得代码更加清晰、简洁和易于维护。因此,在现代软件开发中,观察者模式被广泛应用于处理不同组件之间的高效通信和动态响应问题。 

        

五、局限性和注意事项

5.1 局限性与不适用的场景

    尽管观察者模式为软件开发带来了许多好处,但在某些情况下,它也可能存在局限性和不适用的场景:

 1. 复杂的依赖关系

  • 当系统中的依赖关系变得非常复杂时,观察者模式可能会增加理解和维护的难度。如果观察者之间或观察者与被观察者之间存在复杂的交互逻辑,可能会导致代码变得难以理解和维护。

 2. 性能考虑

  • 在大型系统中,如果观察者数量众多,每次被观察者状态变化时都需要通知所有观察者,这可能会导致性能问题。过多的通知操作可能会消耗大量的计算资源和带宽,影响系统的整体性能。

 3. 循环依赖

  • 如果不小心处理,观察者模式可能会导致循环依赖的问题。例如,观察者A订阅了被观察者B的变化,同时被观察者B又订阅了观察者A的变化。这种情况下,当被观察者B的状态发生变化时,它会通知观察者A,而观察者A在更新自己的状态时又会触发被观察者B的通知,从而形成一个无限循环。

 4. 错误处理

  • 在观察者模式中,当通知观察者时,如果被观察者的通知方法抛出异常,这可能会导致整个系统的不稳定。如果没有妥善处理这些异常,可能会导致系统崩溃或不可预知的行为。

5.2 实际应用中的注意事项与建议

 1. 推送 vs 拉取

  • 在通知观察者时,可以选择推送通知(将状态变化的具体数据发送给观察者)或拉取通知(仅通知观察者去主题上获取需要的数据)。推送方式可能会导致观察者接收不需要的数据,而拉取方式可能导致观察者不知道哪些数据有更新。设计时需要根据实际情况选择更合适的通知机制。

 2. 通知顺序

  • 多个观察者注册到同一个主题时,观察者接收通知的具体顺序可能会影响系统行为。如果某种顺序有特定的业务意义,应该在设计中明确其顺序,并在可能的情况下保持这个顺序的一致性。

 3. 通知效率

  • 如果观察者数量较多或者更新操作比较耗时,主题在通知所有观察者时可能会遭遇性能瓶颈。想要缓解这种情况,可以考虑异步通知机制或使用消息队列处理。

 4. 循环依赖

  • 某个观察者在接收到更新通知后,可能会反过来影响主题状态,从而触发新的通知。该情况如果不加以控制,可能会造成循环调用的问题。设计时要注意辨识并处理潜在的循环依赖问题。

 5. 内存管理

  • 主题通常持有对所有观察者的引用,如果不恰当地进行监听和解除监听,可能会导致内存泄漏。需要确保在观察者生命周期结束时,从主题中正确移除其引用。

 6. 异常处理

  • 当观察者在接收通知时发生异常,不应中断整个通知过程。应该处理每个观察者的异常,尽量减少他们对其他观察者和主题的影响。

 7. 状态一致性

  • 确保观察者在任何时候获取的状态都是一致的。这意味着在状态变更和通知期间,应阻止对状态的任何修改,或者采用一些机制(如状态快照)来保持状态的一致性。

 8. 设计模式的组合使用

  • 有时单纯使用观察者模式可能不足以解决所有问题,可能需要与其他设计模式结合使用,比如命令模式、状态模式或策略模式等,以实现更灵活和健壮的设计。

    在遵守这些注意事项和建议的同时,应该记住设计模式不是万能的,不应该强行适配模式。在选择应用观察者模式前,确保它适合当前的问题场景,并充分考虑它可能带来的设计复杂性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/681399.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【每日一题】牛客网——链表的回文结构

✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有限&#xff0c;欢迎各位大佬指点&#xff0c;相互学习…

OpenCV-38 图像金字塔

目录 一、图像金字塔 1. 高斯金字塔 2. 拉普拉斯金字塔 一、图像金字塔 图像金字塔是图像中多尺度表达的一种&#xff0c;最主要用于图像的分割&#xff0c;是一种以多分辨率来解释图像的有效但概念简单的结构。简单来说&#xff0c;图像金字塔是同一图像不同分辨率的子图…

2000-2021年县域指标统计数据库

2000-2021年县域统计数据库 1、时间&#xff1a;2000-2021年 2、来源&#xff1a;县域统计年鉴 3、范围&#xff1a;2500县 5、指标&#xff1a; 地区名称、年份、行政区域代码、所属城市、所属省份、行政区域土地面积平方公里、乡及镇个数个、乡个数个、镇个数个、街道办…

2024.2.6 模拟实现 RabbitMQ —— 数据库操作

目录 引言 选择数据库 环境配置 设计数据库表 实现流程 封装数据库操作 针对 DataBaseManager 单元测试 引言 硬盘保存分为两个部分 数据库&#xff1a;交换机&#xff08;Exchange&#xff09;、队列&#xff08;Queue&#xff09;、绑定&#xff08;Binding&#xff0…

调用讯飞火星AI大模型WebAPI

调用讯飞火星AI大模型 记录一次调用讯飞AI大模型的过程 官方文档 首先&#xff0c;去官网申请资格&#xff0c;获得必要秘钥等 再编写url&#xff0c;该url存在编码要求&#xff0c;具体看官网url编写 具体代码如下&#xff1a; getWebsocketUrl() {return new Promise((resol…

vivado仿真时使用的代码与实际不一致的解决办法

前言 在使用仿真软件时经常会遇到实际需要时间较长&#xff0c;而仿真需要改写实际代码运行时间的问题&#xff0c;在vivado软件中找到了解决办法 代码部分 这里使用一个最简单的例子来说明一下&#xff0c;学过FPGA的朋友肯定可以看出来就是一个简单的计数器使LED每500ms交…

【MySQL】:分组查询、排序查询、分页查询、以及执行顺序

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; MySQL从入门到进阶 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. 分组查询1.1 语法1.2 where与having区别1.3 注意事项:1.4 案例: 二. 排序查询…

LRU Cache

目录 一、认识LRU Cache 二、LRU Cache实现 一、认识LRU Cache LRU是Least Recently Used的缩写&#xff0c;意思是最近最少使用&#xff0c;是一种Cache替换算法 狭义的Cache指的是位于CPU和主存间的快速RAM&#xff0c; 通常它不像系统主存那样使用DRAM技术&#xff0c;而…

vue三种路由守卫详解

在 Vue 中&#xff0c;可以通过路由守卫来实现路由鉴权。Vue 提供了三种路由守卫&#xff1a;全局前置守卫、全局解析守卫和组件内的守卫。 全局前置守卫 通过 router.beforeEach() 方法实现&#xff0c;可以在路由跳转之前进行权限判断。在这个守卫中&#xff0c;可以根据用…

Vue-自定义属性和插槽(五)

目录 自定义指令 基本语法 (全局&局部注册) 指令的值 练习&#xff1a;v-loading 指令封装 总结&#xff1a; 插槽&#xff08;slot&#xff09; 默认插槽 插槽 - 后备内容&#xff08;默认值&#xff09; 具名插槽 具名插槽基本语法: 具名插槽简化语法: 作…

pytorch花式索引提取topk的张量

文章目录 pytorch花式索引提取topk的张量问题设定代码实现索引方法gather方法验证 补充知识expand方法gather方法randint pytorch花式索引提取topk的张量 问题设定 或者说&#xff0c;有一个(bs, dim, L)的大张量&#xff0c;索引的index形状为(bs, X)&#xff0c;想得到一个(…

HTML世界之第二重天

目录 一、HTML 格式化 1.HTML 文本格式化标签 2.HTML "计算机输出" 标签 3.HTML 引文, 引用, 及标签定义 二、HTML 链接 1.HTML 链接 2.HTML 超链接 3.HTML 链接语法 4.文本链接 5.图像链接 6.锚点链接 7.下载链接 8.Target 属性 9.Id 属性 三、HTML …

王树森《RNN Transformer》系列公开课

本课程主要介绍NLP相关&#xff0c;包括RNN、LSTM、Attention、Transformer、BERT等模型&#xff0c;以及情感识别、文本生成、机器翻译等应用 ShusenWang的个人空间-ShusenWang个人主页-哔哩哔哩视频 (bilibili.com) &#xff08;一&#xff09;NLP基础 1、数据处理基础 数…

Spring Boot 笔记 007 创建接口_登录

1.1 登录接口需求 1.2 JWT令牌 1.2.1 JWT原理 1.2.2 引入JWT坐标 1.2.3 单元测试 1.2.3.1 引入springboot单元测试坐标 1.2.3.2 在单元测试文件夹中创建测试类 1.2.3.3 运行测试类中的生成和解析方法 package com.geji;import com.auth0.jwt.JWT; import com.auth0.jwt.JWTV…

【Spring】公司为什么禁止在SpringBoot项目中使用@Autowired注解

目录 前言 说明 依赖注入的类型 2.1 基于构造器的依赖注入 2.2 基于 Setter 的依赖注入 2.3 基于属性的依赖注入 基于字段的依赖注入缺陷 3.1 不允许声明不可变域 3.2 容易违反单一职责设计原则 3.3 与依赖注入容器紧密耦合 3.4 隐藏依赖关系 总结 参考文档 前言 …

网络协议与攻击模拟_16HTTP协议

1、HTTP协议结构 2、在Windows server去搭建web扫描器 3、分析HTTP协议流量 一、HTTP协议 1、概念 HTTP&#xff08;超文本传输协议&#xff09;用于在万维网服务器上传输超文本&#xff08;HTML&#xff09;到本地浏览器的传输协议 基于TCP/IP(HTML文件、图片、查询结构等&…

数字IC实践项目(9)— Tang Nano 20K: I2C OLED Driver

Tang Nano 20K: I2C OLED Driver 写在前面的话硬件模块RTL电路和相关资源报告SSD1306 OLED 驱动芯片SSD1306 I2C协议接口OLED 驱动模块RTL综合实现 总结 写在前面的话 之前在逛淘宝的时候偶然发现了Tang Nano 20K&#xff0c;十分感慨国产FPGA替代方案的进步之快&#xff1b;被…

自动生成测试用例_接口测试用例自动生成工具

前言 写用例之前&#xff0c;我们应该熟悉API的详细信息。建议使用抓包工具Charles或AnyProxy进行抓包。 har2case 我们先来了解一下另一个项目har2case 他的工作原理就是将当前主流的抓包工具和浏览器都支持将抓取得到的数据包导出为标准通用的 HAR 格式&#xff08;HTTP A…

【AI】安装ubuntu20.04教程(未完待续)

目录 1 制作ubuntu20.04系统盘1.1 下载ubuntu镜像1.2 使用ultraiso写入镜像 2 安装Ubuntu系统 1 制作ubuntu20.04系统盘 1.1 下载ubuntu镜像 在清华镜像站https://mirrors.tuna.tsinghua.edu.cn/下载ubuntu20.04镜像 路径为/ubuntu-releases/20.04/&#xff0c;下载ubuntu-20…

操作系统(16)----磁盘相关

目录 一.磁盘相关概念 1.磁盘 2.磁道 3.扇区 4.盘面、柱面 5.磁盘的分类 二.磁盘调度算法 1.一次磁盘读/写操作需要的时间 2.先来先服务算法(FCFS) 3.最短寻找时间优先(SSTF) 4.扫描算法(SCAN) 5.LOOK调度算法 6.循环扫描算法(C-SCAN) 7.C-LOOK调度算法 三.减少…