当前位置: 首页 > news >正文

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


设计模式专栏: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. 设计模式的组合使用

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

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

相关文章:

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

设计模式专栏&#xff1a;http://t.csdnimg.cn/U54zu 目录 一、引言 核心概念 应用场景 可以解决的问题 二、场景案例 2.1 不用设计模式实现 2.2 存在问题 2.3 使用设计模式实现 2.4 成功克服 三、工作原理 3.1 结构图和说明 3.2 工作原理详解 3.3 实现步骤 四、 优…...

SpringCloud-高级篇(十九)

我们已经学过使用 SpringAMQP去收和发消息&#xff0c;但是发和收消息是只是MQ最基本的功能了&#xff0c;在收发消息的过程中&#xff0c;会有很多的问题需要去解决&#xff0c;下面需要学习rabbitMQ的高级特性去解决 死信交换机&#xff1a;这个可以帮助我们实现消息的延迟的…...

Junit常用断言

0.断言简介 断言:assert Q:断言的作用 更方便的对结果进行判定 "有针对性"的if判断 针对两个变量值是否相同 使用assertEquals针对两个对象是否相同 使用assertSame针对返回值是否为True 使用assertTrue 1.断言的参数 assertXXX(”断言失败时提升的信息“&#x…...

docker 实现 mysql:8.3.0 主从复制(2024年2月13日最新版本)

环境为 CentOS 7.6&#xff0c; 具体操作请看MySQL主从复制01-主从复制概述及原理_哔哩哔哩_bilibili 1、配置主服务器 # 启动主服务器 docker run -p 3306:3306 --name mysql_master -e MYSQL_ROOT_PASSWORDnmnmnm67890890 -v /docker/mysql_master/conf:/etc/mysql/conf.d…...

STM32 + ESP8266,连接阿里云 上报/订阅数据

&#xff08;文章正在编辑中&#xff0c;一点点地截图操作过程&#xff0c;估计要拖拉两三天&#xff09; 一、烧录MQTT固件 ESP8266出厂时&#xff0c;默认是AT固件。连接阿里云&#xff0c;需要使用MQTT固件。 1、独立EPS8266模块的烧录方法 2、魔女开发板&#xff0c;板载…...

如何利用chatgpt提升工作效率?

在数字化和信息化的时代&#xff0c;人工智能技术已经深入到了我们生活的方方面面。其中&#xff0c;ChatGPT作为当前热门的人工智能技术&#xff0c;以其强大的自然语言处理能力和广泛的应用场景&#xff0c;正逐渐改变着我们的工作方式&#xff0c;为我们提高工作效率提供了全…...

MongoDB聚合:$geoNear

$geoNear根据指定的点按照距离以由近到远的顺序输出文档。 从4.2版本开始&#xff0c;MongoDB移除了limit和num选项以及100个文档的限制&#xff0c;如果要限制结果文档的数量可以使用$limit阶段。 语法 { $geoNear: { <geoNear options> } }$geoNear操作接受一个包含…...

Docker-CE 国内源国内镜像

Docker-CE 就是 Docker Community Edition 的意思 docker-ce由docker官方维护 , docker.io由Debian维护 Docker官文 – Install Docker Engine on CentOS Docker官文 – Install Docker Engine on Fedora Docker官文 – Install Docker Engine on Debian Docker官文 – In…...

【Tauri】(3):使用Tauri1.5版本,进行桌面应用开发,在windows上搭建环境,安装node,rust环境,可以打包成功,使用vite创建应用

1&#xff0c;视频地址&#xff1a; https://www.bilibili.com/video/BV1Ny421a7nA/ 【Tauri】&#xff08;3&#xff09;&#xff1a;使用Tauri1.5版本&#xff0c;进行桌面应用开发&#xff0c;在windows上搭建环境&#xff0c;安装node&#xff0c;rust环境&#xff0c;可以…...

C++ 堆排序

C 堆排序 堆排序是一种基于二叉堆数据结构的排序算法&#xff0c;其原理如下&#xff1a; 构建最大堆&#xff1a;将待排序的数组看作一个完全二叉树&#xff0c;并通过调整节点的位置构建一个最大堆。最大堆满足每个父节点的值都大于或等于其子节点的值。构建最大堆的过程可以…...

U3D记录之FBX纹理丢失问题

今天费老大劲从blender建了个模型&#xff0c;然后导出进去unity 发现贴图丢失 上网查了一下 首先blender导出要改设置 这个path mode要copy 然后unity加载纹理也要改设置 这里这个模型的纹理load要改成external那个模式 然后就有了&#xff0c;另外这个导出还有好多选项可…...

监测Nginx访问日志502情况后并做相应动作

今天带大家写一个比较实用的脚本哈 原理&#xff1a; 假设服务器环境为lnmp&#xff0c;近期访问经常出现502现象&#xff0c;且502错误在重启php-fpm服务后消失&#xff0c;因此需要编写监控脚本&#xff0c;一旦出现502&#xff0c;则自动重启php-fpm服务 场景&#xff1a; 1…...

【数据分享】1929-2023年全球站点的逐年平均风速(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 有关气象指标的监测站点数据&#xff0c;之前我们分享过1929-2023年全球气象站…...

Android性能调优 - 应用安全问题

Android应用安全 1.组件暴露&#xff1a; 像比如ContentProvider,BroadcastReceiver&#xff0c;Activity等组件有android:exported属性&#xff1b; 如果是私有组件 android:exported “false”&#xff1b; 如果是公有组件 android:exported “true” 且进行权限控制&…...

C#的Char 结构的像IsLetterOrDigit(Char)等常见的方法

目录 一、Char 结构的方法 二、Char.IsLetterOrDigit 方法 1.Char.IsLetterOrDigit(Char)用法 2.IsLetterOrDigit(String, Int32)方法 三、Char.IsLetter 方法 1.IsLetter(Char) 2.IsLetter(String, Int32) 四、Char.IsDigit 方法 1. IsDigit(String, Int32) 2.IsDig…...

部分意图分类【LLM+RAG】

在生成人工智能领域工作最有价值的事情之一就是发现新兴技术如何融入新的解决方案。 举个例子&#xff1a;在为北美顶级金融服务公司之一设计对话式人工智能助手时&#xff0c;WillowTree 的数据和人工智能研究团队 (DART) 发现&#xff0c;将意图分类与大型语言模型 (LLM) 结合…...

1277. 统计全为 1 的正方形子矩阵

1277. 统计全为 1 的正方形子矩阵 题目链接&#xff1a;1277. 统计全为 1 的正方形子矩阵 代码如下&#xff1a; class Solution { public:int countSquares(vector<vector<int>>& matrix) {if(matrix.size()0||matrix[0].size()0) return 0;//dp[i][j]代表…...

Python 3 时间序列可视化指南

简介 时间序列分析属于统计学的一个分支&#xff0c;涉及对有序的、通常是时间性的数据进行研究。当适当应用时&#xff0c;时间序列分析可以揭示意想不到的趋势&#xff0c;提取有用的统计数据&#xff0c;甚至预测未来的趋势。因此&#xff0c;它被应用于许多领域&#xff0…...

[算法前沿]--059-大语言模型Fine-tuning踩坑经验之谈

前言 由于 ChatGPT 和 GPT4 兴起,如何让人人都用上这种大模型,是目前 AI 领域最活跃的事情。当下开源的 LLM(Large language model)非常多,可谓是百模大战。面对诸多开源本地模型,根据自己的需求,选择适合自己的基座模型和参数量很重要。选择完后需要对训练数据进行预处…...

【Docker】01 Docker安装与配置

文章目录 一、Docker二、离线安装Docker三、联网安装Docker3.1 下载YUM软件库文件3.2 安装epel-release3.3 安装yum-utils3.4 设置镜像仓库3.5 查看docker-ce所有版本3.6 安装Docker3.7 启动Docker3.8 查看Docker信息3.9 启动第一个容器 四、一些配置4.1 登录DockerHub4.2 镜像…...

K8S认证|CKS题库+答案| 8. 沙箱运行容器 gVisor

目录 8. 沙箱运行容器 gVisor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、官网找模板 3&#xff09;、创建 RuntimeClass 4&#xff09;、 将命名空间为 server 下的 Pod 引用 RuntimeClass 5&#xff09…...

c语言超详细知识点总结 1500行手写源码 持续更新中ing 从25年5月到6月5日

想象一下&#xff0c;我们身处的数字世界&#xff0c;如同一座座宏伟的建筑。操作系统、编译器、数据库、嵌入式设备乃至绚丽的游戏引擎&#xff0c;它们都是这座大厦的重要组成部分。而C语言&#xff0c;正是构建这一切的坚固基石。自丹尼斯里奇于贝尔实验室孕育出这颗编程界的…...

JAVA开发工具——IntelliJ IDEA

JAVA开发工具——IntelliJ IDEA 软件下载地址https://www.jetbrains.com/idea/ IDEA项目结构介绍 项目&#xff08;project&#xff09;模块&#xff08;module&#xff09;包&#xff08;package&#xff09;类&#xff08;class) 包含关系&#xff1a;项目 > 模块 >…...

Linux系统的CentOS7发行版安装MySQL80

文章目录 前言Linux命令行内的”应用商店”安装CentOS的安装软件的yum命令安装MySQL1. 配置yum仓库2. 使用yum安装MySQL3. 安装完成后&#xff0c;启动MySQL并配置开机自启动4. 检查MySQL的运行状态 MySQL的配置1. 获取MySQL的初始密码2. 登录MySQL数据库系统3. 修改root密码4.…...

Framework开发之IMS逻辑浅析1--关键线程及作用

关键线程:EventHub,InputReader,InputDispatcher EventHub: 由于Android继承Linux,Linux的思想是一切皆文件,而输入的类型不止一种(触碰&#xff0c;写字笔&#xff0c;键盘等)&#xff0c;每种类型都对应一种驱动设备&#xff0c;而每个硬件驱动设备又对应Linux的一个目录文件…...

二进制安全-IDA Pro-API

idaapi 是 IDA Pro&#xff08;Interactive Disassembler Professional&#xff09; 反汇编工具的 Python API 接口&#xff0c;用于开发自动化脚本、插件和自定义分析工具。通过 idaapi&#xff0c;开发者可以访问 IDA Pro 的核心功能&#xff08;如反汇编、符号分析、交叉引用…...

Java 日期时间类全面解析

Java 日期时间类全面解析&#xff1a;从传统到现代的演进 一、发展历程概览 二、传统日期类&#xff08;Java 8前&#xff09; 1. java.util.Date - 日期表示类 Date now new Date(); // 当前日期时间 System.out.println(now); // Wed May 15 09:30:45 CST 2023// 特定时间…...

RabbitMQ 的高可用性

RabbitMQ 是比较有代表性的&#xff0c;因为是基于主从&#xff08;非分布式&#xff09;做高可用的RabbitMQ 有三种模式&#xff1a;单机模式、普通集群模式、镜像集群模式。 单机模式 单机模式,生产几乎不用。 普通集群模式&#xff08;无高可用性&#xff09; 普通集群模…...

机器学习基础相关问题

机器学习相关的基础问题 K-means是否一定会收敛 K-means是否一定会收敛 K-means算法在有限步数内一定会收敛&#xff0c;但收敛到的可能是局部最优解而非全局最优解。以下是详细分析&#xff1a; K-means 的优化目标是最小化 样本到其所归属簇中心的距离平方和&#xff08;SSE…...

什么是 Ansible 主机和组变量

Ansible 是一款强大的自动化工具&#xff0c;可简化配置管理、应用程序部署和预配等 IT 任务。其最有价值的功能之一是能够定义变量&#xff0c;从而为不同的主机和组定制剧本。本文将解释 Ansible 中组变量和主机变量的概念&#xff0c;并通过实际示例说明它们的用法。 Ansib…...