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

【设计模式-11】责任链模式

认识设计模式(十一)---责任链模式

  • 【一】责任链模式
  • 【二】介绍
    • (1)意图
    • (2)主要解决
    • (3)何时使用
    • (4)如何解决
    • (5)关键代码
    • (6)应用实例
    • (7)优点
    • (8)缺点
    • (9)使用场景
    • (10)注意事项
  • 【三】实现案例
    • (1)介绍
    • (2)创建抽象的记录器类
    • (3)创建扩展了该记录器类的实体类
    • (4)创建不同类型的记录器
  • 【四】更多案例介绍
    • (1)责任链模式解决采购审批问题
      • 1-创建采购请求的实体类
      • 2-创建抽象的采购审批类
      • 3-创建扩展了该审批类的实体类
      • 4-设置责任链,测试类
    • (2)责任链模式解决登录过程的数据校验问题
      • 1-创建一个实体类Member
      • 2-传统方式的登录校验代码
      • 3-开始使用责任链模式优化,创建抽象的处理类Handler
      • 4-创建扩展了处理类的实体类
      • 5-在服务层设置链
      • 6-测试代码
      • 7-责任链模式+建造者模式结合使用优化

【一】责任链模式

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

【二】介绍

(1)意图

避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

(2)主要解决

职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

(3)何时使用

在处理消息的时候以过滤很多道。

(4)如何解决

拦截的类都实现统一接口。

(5)关键代码

Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。

(6)应用实例

1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡。 3、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。

(7)优点

1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。

(8)缺点

1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。

(9)使用场景

1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求。

(10)注意事项

在 JAVA WEB 中遇到很多应用。

【三】实现案例

(1)介绍

我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录器。
在这里插入图片描述

(2)创建抽象的记录器类


public abstract class AbstractLogger {public static int INFO = 1;public static int DEBUG = 2;public static int ERROR = 3;protected int level;//责任链中的下一个元素protected AbstractLogger nextLogger;public void setNextLogger(AbstractLogger nextLogger){this.nextLogger = nextLogger;}public void logMessage(int level, String message){// 如果传的参数level大于等于已有的level,则写日志if(this.level <= level){write(message);}// 如果下一个记录器不为nullif(nextLogger !=null){nextLogger.logMessage(level, message);}}abstract protected void write(String message);}

(3)创建扩展了该记录器类的实体类

public class ConsoleLogger extends AbstractLogger {public ConsoleLogger(int level){this.level = level;}@Overrideprotected void write(String message) {    System.out.println("Standard Console::Logger: " + message);}
}public class ErrorLogger extends AbstractLogger {public ErrorLogger(int level){this.level = level;}@Overrideprotected void write(String message) {    System.out.println("Error Console::Logger: " + message);}
}public class FileLogger extends AbstractLogger {public FileLogger(int level){this.level = level;}@Overrideprotected void write(String message) {    System.out.println("File::Logger: " + message);}
}

(4)创建不同类型的记录器

创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。


public class ChainPatternDemo {private static AbstractLogger getChainOfLoggers(){AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);errorLogger.setNextLogger(fileLogger);fileLogger.setNextLogger(consoleLogger);return errorLogger;  }public static void main(String[] args) {AbstractLogger loggerChain = getChainOfLoggers();loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");loggerChain.logMessage(AbstractLogger.DEBUG, "This is a debug level information.");loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information.");}
}

输出结果

Standard Console::Logger: This is an information.
File::Logger: This is a debug level information.
Standard Console::Logger: This is a debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.

【四】更多案例介绍

(1)责任链模式解决采购审批问题

1-创建采购请求的实体类

/*** @ClassName: PurchaseRequest* @Author: AllenSun* @Date: 2020/3/9 22:36*/
public class PurchaseRequest {private int type=0;private float price=0.0f;private int id=0;public PurchaseRequest(int type, float price, int id) {this.type = type;this.price = price;this.id = id;}public int getType() {return type;}public float getPrice() {return price;}public int getId() {return id;}
}

2-创建抽象的采购审批类

/*** @ClassName: Approver* @Author: AllenSun* @Date: 2020/3/9 22:31*/
public abstract class Approver {//下一个处理者Approver approver;//名字String name;public Approver(String name) {this.name = name;}//下一个处理者public void setApprover(Approver approver) {this.approver = approver;}//处理审批请求的方法,得到一个请求,处理是子类完成,因此该方法做成抽象public abstract void processRequest(PurchaseRequest purchaseRequest);
}

3-创建扩展了该审批类的实体类

/*** @ClassName: CollegeApprover* @Author: AllenSun* @Date: 2020/3/9 22:34*/
public class DepartmentApprover extends Approver {public DepartmentApprover(String name) {super(name);}@Overridepublic void processRequest(PurchaseRequest purchaseRequest) {if(purchaseRequest.getPrice()<=5000){System.out.println("请求编号id="+purchaseRequest.getId()+"被"+this.name+"处理");} else {approver.processRequest(purchaseRequest);}}
}/*** @ClassName: CollegeApprover* @Author: AllenSun* @Date: 2020/3/9 22:34*/
public class CollegeApprover extends Approver {public CollegeApprover(String name) {super(name);}@Overridepublic void processRequest(PurchaseRequest purchaseRequest) {if(purchaseRequest.getPrice()>5000&&purchaseRequest.getPrice()<=10000){System.out.println("请求编号id="+purchaseRequest.getId()+"被"+this.name+"处理");} else {approver.processRequest(purchaseRequest);}}
}/*** @ClassName: CollegeApprover* @Author: AllenSun* @Date: 2020/3/9 22:34*/
public class ViceSchoolMasterApprover extends Approver {public ViceSchoolMasterApprover(String name) {super(name);}@Overridepublic void processRequest(PurchaseRequest purchaseRequest) {if(purchaseRequest.getPrice()>10000&&purchaseRequest.getPrice()<=30000){System.out.println("请求编号id="+purchaseRequest.getId()+"被"+this.name+"处理");} else {approver.processRequest(purchaseRequest);}}
}/*** @ClassName: CollegeApprover* @Author: AllenSun* @Date: 2020/3/9 22:34*/
public class SchoolMasterApprover extends Approver {public SchoolMasterApprover(String name) {super(name);}@Overridepublic void processRequest(PurchaseRequest purchaseRequest) {if(purchaseRequest.getPrice()>30000){System.out.println("请求编号id="+purchaseRequest.getId()+"被"+this.name+"处理");} else {approver.processRequest(purchaseRequest);}}
}

4-设置责任链,测试类

/*** @ClassName: Client* @Author: AllenSun* @Date: 2020/3/9 22:50*/
public class Client {public static void main(String[] args) {//创建一个请求PurchaseRequest purchaseRequest=new PurchaseRequest(1,31000,1);//创建相关的审批人DepartmentApprover departmentApprover=new DepartmentApprover("张主任");CollegeApprover collegeApprover=new CollegeApprover("李院长");ViceSchoolMasterApprover viceSchoolMasterApprover=new ViceSchoolMasterApprover("王副校长");SchoolMasterApprover schoolMasterApprover=new SchoolMasterApprover("孙校长");//需要把各个审批级别的下一个设置好(处理人构成环形)departmentApprover.setApprover(collegeApprover);collegeApprover.setApprover(viceSchoolMasterApprover);viceSchoolMasterApprover.setApprover(schoolMasterApprover);schoolMasterApprover.setApprover(departmentApprover);departmentApprover.processRequest(purchaseRequest);viceSchoolMasterApprover.processRequest(purchaseRequest);}
}

(2)责任链模式解决登录过程的数据校验问题

在日常生活中责任链模式还是比较常见的,我们平时工作处理一些事务,往往是各部门协同合作的完成—个任务。而每个部门都有各自的职责,因此,很多时候事谓完成—半,便会转交给下—个部门,直到所有部门都过一渔之后事谓才能完成。

1-创建一个实体类Member

@Data
public class Member {private String loginName;private String loginPass;private String roleName;public Member(String loginName, String loginPass) {this.loginName = loginName;this.loginPass = loginPass;}
}

2-传统方式的登录校验代码

public class MemberService {public static void main(String[] args) {MemberService service = new MemberService();service.login("tom", "666");}public void login(String loginName, String loginPass) {if (StringUtils.isEmpty(loginName) ||StringUtils.isEmpty(loginPass)) {System.out.println("用户名和密码为空");return;}System.out.println("用户名和密码不为空,可以往下执行");Member member = checkExists(loginName, loginPass);if (null == member) {System.out.println("用户不存在");return;}System.out.println("登录成功!");if (!"管理员".equals(member.getRoleName())) {System.out.println("您不是管理员,没有操作权限");return;}System.out.println("允许操作");}private Member checkExists(String loginName, String loginPass) {Member member = new Member(loginName, loginPass);member.setRoleName("管理员");return member;}
}

3-开始使用责任链模式优化,创建抽象的处理类Handler

public abstract class Handler {protected Handler next;public void next(Handler next){ this.next = next;}public abstract void doHandler(Member member);
}

4-创建扩展了处理类的实体类

我们分别创建非空校验ValidateHandler类、登录校验LoginHandler类和权限校验AuthHandler类

public class ValidateHandler extends Handler {public void doHandler(Member member) {if (StringUtils.isEmpty(member.getLoginName()) ||StringUtils.isEmpty(member.getLoginPass())) {System.out.println("用户名和密码为空");return;}System.out.println("用户名和密码不为空,可以往下执行");next.doHandler(member);}
}public class LoginHandler extends Handler {public void doHandler(Member member) {System.out.println("登录成功!");member.setRoleName("管理员");next.doHandler(member);}
}public class AuthHandler extends Handler {public void doHandler(Member member) {if (!"管理员".equals(member.getRoleName())) {System.out.println("您不是管理员,没有操作权限");return;}System.out.println("允许操作");}
}

5-在服务层设置链

public class MemberService {public void login(String loginName, String loginPass) {Handler validateHandler = new ValidateHandler();Handler loginHandler = new LoginHandler();Handler authHandler = new AuthHandler();validateHandler.next(loginHandler);loginHandler.next(authHandler);validateHandler.doHandler(new Member(loginName, loginPass));}
}

6-测试代码

public class Test {public static void main(String[] args) {MemberService memberService = new MemberService();memberService.login("tom","666");}
}

测试结果

用户名和密码校验成功,可以往下执行
登录成功!
您是管理员,允许操作

7-责任链模式+建造者模式结合使用优化

因为责任链模式具备链式结构,而上面代码中,我们看到,负责组装链式结构的角色是
MemberService ,当链式结构较长时,MemberService的工作会非常繁琐,并且MemberService代码相对臃肿,且后续更改处理者或消息类型时,都必须在MemberService中进行修改,不符合开闭原则。产生这些问题的原因就是因为链式结构的组装过于复杂,而对于复杂结构的创建,很自然我们就会想到建造者模式,使用建造者模式,我们完全可以MemberService指定的处理节点对象进行自动链式组装,客户只需指定处理节点对象,其他任何事情都无需关心,并且客户指定的处理节点对象顺序不同 ,构造出来的链式结构也随之不同。我们来改造一下,修改Handler的代码:

public abstract class Handler<T> {protected Handler next;//public void next(Handler next){ this.next = next;}private void next(Handler next){ this.next = next;}public abstract void doHandler(Member member);public static class Builder<T>{private Handler<T> head;private Handler<T> tail;public Builder<T> addHandler(Handler handler){// do {if (this.head == null) {this.head = this.tail = handler;return this;}this.tail.next(handler);this.tail = handler;// }while (false);//真正框架中,如果是双向链表,会判断是否已经到了尾部return this;}public Handler<T> build(){return this.head;}}
}

然后 ,修改MemberService的代码:

public class MemberService {public void login(String loginName,String loginPass){Handler.Builder builder = new Handler.Builder();builder.addHandler(new ValidateHandler()).addHandler(new LoginHandler()).addHandler(new AuthHandler());builder.build().doHandler(new Member(loginName,loginPass));//用过Netty的人,肯定见过}
}

相关文章:

【设计模式-11】责任链模式

认识设计模式&#xff08;十一&#xff09;---责任链模式【一】责任链模式【二】介绍&#xff08;1&#xff09;意图&#xff08;2&#xff09;主要解决&#xff08;3&#xff09;何时使用&#xff08;4&#xff09;如何解决&#xff08;5&#xff09;关键代码&#xff08;6&am…...

SpringBoot+Vue实现智能物流管理系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏…...

【MT7628】MT7628如何修改串口波特率、调试串口物理口、使用UART3口

环境说明 sdk版本:Mediatek_ApSoC_SDK_4320_20150414.tar.bz2 芯片方案:MT7628A Uboot修改串口波特率方法 修改rt2880.h文件 修改include/configs/rt2880.h文件CONFIG_BAUDRATE宏的值 - #define CONFIG_BAUDRATE 57600 +#define CONFIG_BAUDRATE 115200 Kernel中修改串口波特…...

css盒模型介绍

在使用CSS进行网页布局时&#xff0c;我们一定离不开的一个东西————盒子模型。盒子模型&#xff0c;顾名思义&#xff0c;盒子就是用来装东西的&#xff0c;它装的东西就是HTML元素的内容。或者说&#xff0c;每一个可见的 HTML 元素都是一个盒子&#xff0c;下面所说的盒子…...

onetab 谷歌插件历史数据清除

文章目录方法1&#xff1a;测试也可以步骤1&#xff1a;批量执行点击步骤2&#xff1a;python 脚本模拟点击确定操作方法2&#xff1a;成功【推荐】步骤1&#xff1a;修改confirm&#xff0c;类似于hook操作步骤2&#xff1a;批量点击删除操作&#xff1a;onetab 谷歌插件历史数…...

GRBL源码简单分析

结构体说明 GRBL里面的速度规划是带运动段前瞻的&#xff0c;所以有规划运动段数据和微小运动段的区分 这里的“规划运动段”对应的数据结构是plan_block_t&#xff0c;前瞻和加减速会使用到&#xff0c;也就是通过解析G代码后出来的直接直线数据或是圆弧插补出来的拟合直线数据…...

第一部分:简单句——第一章:简单句的核心——二、简单句的核心变化(谓语动词的情态)

二、简单句的核心变化 简单句的核心变化其实就是 一主一谓&#xff08;n. v.&#xff09; 表达一件事情&#xff0c;谓语动词是其中最重要的部分&#xff0c;谓语动词的变化主要有四种&#xff1a;三态加一否&#xff08;时态、语态、情态、否定&#xff09;&#xff0c;其中…...

软考高级考试中有五大证书,其中哪个更值得考?

计算机软考属于专业技术人员职业资格水平评价类&#xff0c;是职业资格、专业技术资格&#xff08;职称&#xff09;和专业技术水平"三合一"的考试&#xff0c;是目前IT行业仅有的国家级考试。考试不受学历、专业、资历等条件限制。软考高级考试中有五大证书&#xf…...

FlexRay™ 协议控制器 (E-Ray)-04

网络管理 累积的网络管理 (NM) 向量位于网络管理寄存器 1 到网络管理寄存器 3 (NMVx (x = 1-3)) 中。【The accrued Network Management (NM) vector is located in the Network Management Register 1 to Network Management Register 3 (NMVx (x = 1-3)).】 网络管理向量 x…...

container_of 根据成员变量获得包含其的对象的地址!

写在前面 本系列文章的灵感出处均是各个技术书籍的读后感&#xff0c;详细书籍信息见文章最后的参考文献 CONTAINER_OF 在书中发现一个很有意思的宏&#xff0c;以此可以衍生出来其很多的用法&#xff0c;这个宏可以根据某个成员变量的地址得到包含这个成员变量地址的对象的…...

Linux进程概念

Linux进程概念前言冯诺依曼体系操作系统设计操作系统的目的如何理解OS是一款搞“管理”的软件&#xff1f;系统调用和库函数的概念进程的概念描述进程组织进程查看进程fork&#xff08;&#xff09;前言 本篇博客主要介绍一些&#xff1a;冯诺依曼体系、OS的理解、进程的一些概…...

算法设计与分析

两个例子:调度问题与投资问题 例1&#xff1a;调度问题 问题 有 n 项任务&#xff0c;每项任务加工时间已知.从 0时刻开始陆续安排到一台机器上加工. 每个任务的完成时间是从 0 时刻到任务加工截止的时间. 求: 总完成时间&#xff08;所有任务完成时间之和&#xff09;最短…...

C++ 基础

命名空间 在 C/C 中&#xff0c;变量、函数和类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c;以避免命名冲突或名字污染&#xff0c;namespace 关键字的…...

[golang gin框架] 2.Gin HTML模板渲染以及模板语法,自定义模板函数,静态文件服务

一.Gin HTML 模板渲染全部模板放在一个目录里面的配置方法首先在项目根目录新建 templates 文件夹&#xff0c;然后在文件夹中新建 对应的index.html<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta http…...

数据仓库层Repository(CrudRepository、PagingAndSortingRepository、JpaRepository)

什么是数据仓库层Repository&#xff1f; 数据仓库接口的作用&#xff1a;Repository原意指的是仓库&#xff0c;即数据仓库的意思。Repository居于业务层和数据层之间&#xff0c;将两者隔离开来&#xff0c;在它的内部封装了数据查询和存储的逻辑。 Repository接口&#xff…...

大数据技术架构(组件)33——Spark:Spark SQL--Join Type

2.2.2、Join Type2.2.2.1、Broadcast Hash Join (Not Shuffled)就是常说的MapJoin,join操作在map端进行的。场景&#xff1a;join的其中一张表要很小&#xff0c;可以放到Driver或者Executor端的内存中。原理:1、将小表的数据广播到所有的Executor端&#xff0c;利用collect算子…...

Linux: bash起后台进程引发的僵尸进程

1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. 案例 原来的故事是 这样 的&#xff0c;感兴趣的读者可以直接前往。我从中截取了一段重现故事中问题的代码&#xff08;对原代码做了小小调整&a…...

网络安全攻防中,Rock-ON自动化的多功能网络侦查工具,Burpsuite被动扫描流量转发

网络安全攻防中&#xff0c;Rock-ON自动化的多功能网络侦查工具&#xff0c;Burpsuite被动扫描流量转发。 #################### 免责声明&#xff1a;工具本身并无好坏&#xff0c;希望大家以遵守《网络安全法》相关法律为前提来使用该工具&#xff0c;支持研究学习&#xff…...

电子技术——共模抑制

电子技术——共模抑制 我们在之前学习过&#xff0c;无论是MOS还是BJT的差分输入对&#xff0c;共模信号并不会改变漏极电流的大小&#xff0c;因此我们说差分输入对共模信号无响应。但是实际上由于各种客观非理想因素&#xff0c;例如电流源有限阻抗等&#xff0c;此时共模是影…...

对KMP简单的理解

声明&#xff1a;下边的例子均表示下标从1开始的数组 ne数组的定义&#xff1a; next[i] 就是使子串 s[1…i] 有最长相等前后缀的前缀的最后一位的下标。ne[i]也可以表示相等子串的长度 准备执行jne[j]时&#xff0c; 表示当前s[i]!p[j1] , 如果ne[j]1 &#xff0c;那么下…...

Hibernate不是过时了么?SpringDataJpa又是什么?和Mybatis有什么区别?

一、前言 ps: 大三下学期&#xff0c;拿到了一份实习。进入公司后发现用到的技术栈有Spring Data Jpa\Hibernate,但对于持久层框架我只接触了Mybatis\Mybatis-Plus&#xff0c;所以就来学习一下Spring Data Jpa。 1.回顾MyBatis 来自官方文档的介绍&#xff1a;MyBatis 是一款…...

数学建模拓展内容:卡方检验和Fisher精确性检验(附有SPSS使用步骤)

卡方检验和Fisher精确性检验卡方拟合度检验卡方独立性检验卡方检验的前提假设Fisher精确性检验卡方拟合度检验 卡方拟合度检验概要&#xff1a;卡方拟合度检验也被称为单因素卡方检验&#xff0c;用于检验一个分类变量的预期频率和观察到的频率之间是否存在显著差异。 卡方拟…...

【Python学习笔记之七大数据类型】

Python数据类型&#xff1a;Number数字、Boolean布尔值、String字符串、list列表、tuple元组、set集合、dictionary字典 int整数 a1 print(a,type(a))float浮点数 b1.1 print(b,type(b))complex复数 c100.5j print(c,type(c))bool布尔值:True、False,true和false并非Python…...

Android系统之onFirstRef自动调用原理

前言&#xff1a;抽丝剥茧探究onFirstRef究竟为何在初始化sp<xxx>第一个调用&#xff1f;1.onFirstRef调用位置<1>.system/core/libutils/RefBase.cpp#include <utils/RefBase.h>//1.初始化强指针 void RefBase::incStrong(const void* id) const {weakref_i…...

ipv6上网配置

一般现在的宽带都已经支持ipv6了&#xff0c;但是需要一些配置才能真正用上ipv6。记录一下配置过程。 当前测试环境为移动宽带&#xff0c;光猫下面接了一个路由器&#xff0c;家里所有的设备都挂到这个路由器下面的。 1. 光猫改桥接 光猫在使用路由模式下&#xff0c;ipv6无…...

python实现聚类技术—复杂网络社团检测 附完整代码

实验内容 某跆拳道俱乐部数据由 34 个节点组成,由于管理上的分歧,俱乐部要分解成两个社团。 该实验的任务即:要求我们在给定的复杂网络上检测出两个社团。 分析与设计 实验思路分析如下: 聚类算法通常可以描述为用相似度来衡量两个数据的远近,搜索可能的划分方案,使得目标…...

如何判断两架飞机在汇聚飞行?(如何计算两架飞机的航向夹角?)内含程序源码

ok&#xff0c;在开始一切之前&#xff0c;让我先猜一猜&#xff0c;你是不是想百度“二维平面下如何计算两个移动物体的航向夹角&#xff1f;”如果是&#xff0c;那就请继续往下看。 首先&#xff0c;我们要明确一个概念&#xff1a;航向角≠航向夹角&#xff01;&#xff0…...

Scipy稀疏矩阵bsr_array

文章目录基本原理初始化内置方法基本原理 bsr&#xff0c;即Block Sparse Row&#xff0c;bsr_array即块稀疏行矩阵&#xff0c;顾名思义就是将稀疏矩阵分割成一个个非0的子块&#xff0c;然后对这些子块进行存储。通过输入维度&#xff0c;可以创建一个空的bsr数组&#xff0…...

LeetCode笔记:Weekly Contest 332

LeetCode笔记&#xff1a;Weekly Contest 332 1. 题目一 1. 解题思路2. 代码实现 2. 题目二 1. 解题思路2. 代码实现 3. 题目三 1. 解题思路2. 代码实现 4. 题目四 1. 解题思路2. 代码实现 比赛链接&#xff1a;https://leetcode.com/contest/weekly-contest-332/ 1. 题目一…...

autox.js在vscode(win7)与雷神模拟器上的开发环境配置

目录 下载autox.js 安装autox.js&#xff1f; 在电脑上搭建autox.js开发环境 安装vscode 安装autox.js插件 雷神模拟器连接vscode 设置雷神模拟器IP 设置autox.js应用IP地址等 下载autox.js 大体来说&#xff0c;就是一个运行在Android平台上的JavaScript 运行环境 和…...

商品的销售网站总体设计/抚州seo外包

http://www.cnblogs.com/xiaosha/p/3362512.html最近netbean出了免费&#xff0c;社区版pycharm&#xff1b;补全&#xff0c;语法识别&#xff0c;折叠&#xff0c;debug功能都有安装在Ubutnu 13.04系统下&#xff0c;需要oracle jre首先安装oracle jreOracle Jre 下载地址&am…...

陕西省住房和城乡建设厅网站/互联网销售包括哪些

拓扑图判环使用拓扑排序判断无向图和有向图中是否存在环的区别在于&#xff1a; 在判断无向图中是否存在环时&#xff0c;是将所有度 < 1 的结点入队&#xff1b; 在判断有向图中是否存在环时&#xff0c;是将所有入度 0 的结点入队。...

织梦英文版网站怎么做/建设网站制作

DNS 重要参数1 dns 安装####################################################################yum install -y bind 2 vi /etc/named.conf ############这些参数非常重要&#xff0c;缺一利用私有网络搭建DNS 转发器将导致失败。options {listen-on port 53 { any; };forwar…...

义乌网站建设优化案例/网站测试报告

1、安装vue-router插件npm install vue-router --save其中--save是为了保存在package.json配置中&#xff0c;写在配置文件中下次install的时候&#xff0c;依赖包就会按照json文件中的配置项进行安装2、在src中新建一个配置动态路由的js文件&#xff0c;js文件主要配置对应的路…...

北京规划网站/长沙网站建设

一、前言在前一篇博客中&#xff0c;小编向大家介绍了《使用idea搭建SSM框架》&#xff0c;如果按照小编的步骤做下来&#xff0c;基本上是没有问题的。但是这个只是一个简单的SSM架构&#xff0c;在上线的项目中&#xff0c;这种架构只能满足一些用户量比较小的项目&#xff0…...

wordpress显示/成品短视频网站源码搭建

一行代码的事情&#xff0c;...