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

基于策略模式企业实战中策略命中设计

背景

在公司实际项目项目开发中,有一个策略命中的开发需求。根据用户请求参数的不同来动态返回不同的业务数据。比如说有城市、客户年龄、请求时间3个策略维度,不同的城市返回不同的地区的地标,根据时间地标的背景色要发生变化等等的需求。当然,如果你直接使用一堆的嵌套if/else来硬代码编写这个业务的话,确实也行。那难度再升级一下,有20个策略维度的话,这代码谁维护谁跑路。

所以我们要用合理规范的设计模式来实现该功能。

方案拟定

先来了解一下策略模式的概念:

策略模式是一种设计模式,它定义了一系列算法,并将每个算法封装起来,使他们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

在Java中,可以使用如下步骤实现策略模式:

  1. 定义策略接口,该接口定义了所有算法的公共接口。
  2. 实现策略接口,为每种算法实现一个具体策略类。
  3. 创建一个上下文类,该类持有一个策略类的引用,并且实现策略接口的方法。
  4. 客户端代码中,创建一个上下文对象,并设置一个具体策略对象。

策略模式的意义在于:

  1. 可以让算法和业务代码分离,使得算法可以独立演化,不会影响业务代码。
  2. 可以在不修改业务代码的情况下更换算法,提高了系统的灵活性。
  3. 可以很容易地扩展新的算法,而不需要修改原有的代码。
  4. 可以减少代码的冗长,使代码更加清晰易读。

简单来说的话,就是创建一个接口,该接口定义一个公共的方法,实现类继承这个接口,实现具体的功能。再创建一个service类,对外提供服务时是通过这个类去动态传入实际处理逻辑的实现类去完成任务。

需求分析

结合实际业务场景来设计代码演练一下,拿上面的需求来开发。案例中我们来实现城市、客户年龄、请求时间3个策略维度的命中功能判断服务。

功能刨析:

  1. 需要一个定义了策略接口IStrategy,接口中有执行策略判断方法executeStrategy();
  2. 城市策略CityStrategy、客户年龄AgeStrategy、请求时间策略RquestTimeStrategy都实现IStrategy接口
  3. 策略实现类StrategyService是对外实现策略命中的类

大局来看主要是这3部分,细节我们在下面的章节来补充。

策略模式架构代码实现

准备工作

  1. 封装请求报文中的策略类
@Data 
public class RequestStrategyInfo {private String cityInfo;private String ageInfo;private String requestTime;....
}

1. 定义策略统一接口

public interface IStrategy {boolean executeStrategy();
}

2. 各个策略实现IStrategy接口

城市策略

public class CityStrategy implements IStrategy {@Overridepublic boolean executeStrategy() {}
}

年龄策略

public class AgeStrategy implements IStrategy {@Overridepublic boolean executeStrategy() {}
}

请求时间策略

public class RquestTimeStrategy implements IStrategy {@Overridepublic boolean executeStrategy() {}
}

3. StrategyService 对外提供策略匹配服务

StrategyService是最重要的,在这个类里,它要识别出当前判断的策略需要调用哪个具体的策略实例来执行,这有好几种方法:

  1. 策略工厂
import java.lang.reflect.InvocationTargetException;public class StrategyFactory {@Overridepublic IStrategy createStrategy(String strategyType) {try {Class<?> strategyClass = Class.forName(strategyType);return (IStrategy) strategyClass.getDeclaredConstructor().newInstance();} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {e.printStackTrace();}return null;}
}
public class StrategyService {private IStrategy strategy;private StrategyFactory strategyFactory;public boolean executeStrategy() {// 是否支持任意策略if (strategyInfo.getIsAll()) {return true;}// 获取从数据库详细的策略信息StrategyItem si = strategyItemService.qryStrategyItem(itemId);String strategyType = si.getStrategyType();// 根据strategyType获得对应的策略实例strategy = strategyFactory.createStrategy(strategyType);// 执行策略匹配规则return strategy.executeStrategy();}
}

这种方法可以完成动态找到需要的实现类,不过要求strategyType与类名有强关联关系,必须要通过strategyType来创建实例,也可通过定义枚举类来进一步解耦。

  1. 在上面的基础上定义枚举类StrategyEnum进行解耦
public enum StrategyType {CityStrategy("city", CityStrategy.class),AgeStrategy("age", AgeStrategy.class),RequestTimeStrategy("requestTime", RequestTimeStrategy.class);private String strategyType;private Class<? extends IStrategy> strategyClass;SortType(String sortType, Class<? extends IStrategy> strategyClass) {this.strategyType = strategyType;this.strategyClass = strategyClass;}public Class<? extends IStrategy> getStrategyClassBySortType(String strategyType) {StrategyType[] values = StrategyType.values();return Arrays.stream(values).filter(it -> it.strategyType.equals(strategyType)).findFirst().get().strategyClass;}
}

StrategyService需要稍微改造

public class StrategyService {private IStrategy strategy;private StrategyFactory strategyFactory;public boolean executeStrategy() {// 是否支持任意策略if (strategyInfo.getIsAll()) {return true;}// 获取从数据库详细的策略信息StrategyItem si = strategyItemService.qryStrategyItem(itemId);String strategyType = si.getStrategyType();// 根据strategyType获得对应的策略实例// strategy = strategyFactory.createStrategy(strategyType);try {strategy = StrategyType.getStrategyClassBySortType(strategyType).newInstance();} catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();}// 执行策略匹配规则return strategy.executeStrategy();}
}

使用枚举可以解耦strategyType和策略类名的关系,在枚举里面维护对应关系,以后如果有新的策略,直接添加枚举即可。

  1. 如果第二种方法不喜欢的话,可以通过在StrategyService中定义一个Map集合维护strategyType与类名的关系
public class StrategyService {private Map<String, Class<? extends IStrategy>> strategyMap;public StrategyService() {strategyMap = new HashMap<>();strategyMap.put("city", CityStrategy.class);strategyMap.put("age", AgeStrategy.class);strategyMap.put("requestTime", RequestTimeStrategy.class);}private IStrategy strategy;private StrategyFactory strategyFactory;public boolean executeStrategy() {// 是否支持任意策略if (strategyInfo.getIsAll()) {return true;}// 获取从数据库详细的策略信息StrategyItem si = strategyItemService.qryStrategyItem(itemId);String strategyType = si.getStrategyType();// 根据strategyType获得对应的策略实例// strategy = strategyFactory.createStrategy(strategyType);/*try {strategy = StrategyType.getStrategyClassBySortType(strategyType).newInstance();} catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();}*/Class<? extends IStrategy> strategyClass = strategyMap.get(strategyType);if (Class<? extends IStrategy> strategyClass = strategyMap.get(strategyType);== null) {throw new IllegalArgumentException("Unsupported strategy type: " + strategyType);}try {strategy = strategyClass.getDeclaredConstructor().newInstance();} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {e.printStackTrace();}// 执行策略匹配规则return strategy.executeStrategy();}
}

用Map维护映射的话,需要考虑策略的数量,如果数量巨大的话,对性能开销可不容小看的;而且这种映射关系手动维护在类里面的做法,可能不太优雅。

  1. 如果你觉得上述3种方法的硬代码、耦合度都达不到你公司的标准,你可以选择程序在初始化时动态加载全部 IStrategy 接口下的实现类实例到ArrayList中的方式

在自动选择策略时,会遍历一遍所有的策略是否支持当前操作策略类型。在选择使用这种方式前,需要对IStrategy接口进行改造:

public interface IStrategy {boolean executeStrategy();// 当前实现类是否支持boolean support(String strategyType);
}

实现类中对support()方法进行完善,举个例子,比如城市策略:

public class CityStrategy implements IStrategy {@Overridepublic boolean executeStrategy() {}@Overridepublic boolean support(String strategyType) {return "CityStrategy".equals(strategyType);}
}

其余策略方式一致,可考虑将字符串定义成常量在IStrategy接口中,这样会更规范一点

在StrategyService中使用时,需要在初始化时先将IStrategy接口下的所有实现类放到ArrayList中,提供给executeStrategy()方法使用

public class StrategyService implements InitializingBean {@Autowiredprivate ApplicationContext appContext;private Collection<IStrategy> strategys;private IStrategy strategy;private StrategyFactory strategyFactory;public boolean executeStrategy() {// 是否支持任意策略if (strategyInfo.getIsAll()) {return true;}// 获取从数据库详细的策略信息StrategyItem si = strategyItemService.qryStrategyItem(itemId);String strategyType = si.getStrategyType();// 根据strategyType获得对应的策略实例IStrategy strategy = strategys.parallelStream().filter(it -> it.support(strategyType)).findFirst().get();// 执行策略匹配规则return strategy.executeStrategy();}@Overridepublic void afterPropertiesSet() throws Exception() {Map<String, IStrategy> strategyMap = appContext.getBeansOfType(IStrategy.class);strategys = strategyMap.values();}
}

这种方法不需要保证strategyType和策略类名的一一对应关系,是解耦最为激进的一种方式。但是如果策略数量非常多,遍历整个列表可能带来性能问题。

没有最好的方法,只有最适合的方法。如果策略数量不多,那么使用Map来存储映射关系是一个好的选择。如果策略数量非常多,而且不需要频繁地添加和移除策略,那么使用抽象的策略工厂是一个不错的选择。如果策略数量非常多,进一步考虑一定的解耦性,可添加枚举类解耦。如果对解耦的需求更重要于性能考虑,可考虑使用ArrayList遍历的方法。

业务绑定策略设计与代码实现

上一章节只讲述了策略模式架构的设计与不同场景选择策略实例的方式,这一章相当于上一章节的前传。要先有业务绑定了策略之后,请求业务才有策略匹配。

【根据用户请求参数的不同来动态返回不同的业务数据。】这个业务的场景是有一个管理后台,去设定某个业务绑定某些策略。当客户端带着请求参数来访问该业务时,我们要对请求参数的某些字段的值与该业务选择的策略值进行一一比较,若全都符合时,方可返回该业务数据。

实体类设计

城市、年龄、时间等这些定义为策略类型,城市中包含广州、上海、北京、深圳,年龄有18、19、20这些定义为策略值

策略类型实体类为StrategyType

@Data
public class StrategyType {private Long id;			// 主键private String type;		// 类型private String name;		// 类型名称private String oper;		// 支持的操作
}

策略值实体类为StrategyValue

public class StrategyValue {private Long id;		// 主键private Long typeId;	// 策略类型idprivate String value;	// 策略值
}

单单有策略类型与其具体的策略值是不够的,业务如何绑定策略?我们假设操作上是这样的一个流程:在创建好一个业务之后,选择关联策略,城市选择广州,年龄选择等于(大于、小于)18,点击保存。捋一下这两者的关系不难发现,业务与策略值之间是多对多的关系。数据库层面还需要要建一个关联表。

关键字段有:业务id、策略值id、操作类型

操作类型有:等于、大于、小于、不等于;

这个思路去做可以实现灵活度非常高的策略配置,但缺点就是如果每个业务都需要配置多个策略,尤其是一些策略几乎每个都要配置的,那每次都要进行相同的多次操作确实很烦人。

在这里我给出的优化建议有两个,第一个是保存历史操作记录,业务添加策略时读取操作记录表的数据,操作记录保存多少条这个看具体情况而定;第二个是新增一个复合策略表,可以组合一些常用的复合策略,比如广州市18岁策略,在选择策略时可以选择复合策略。

业务绑定策略并没有什么复杂操作,代码主要与业务代码镶嵌,不方便举例。查找出业务绑定的策略时,封装成一个对象。

@Data
public class StrategyDetail {private Long id;private String type;private String oper;private String value;
}

策略匹配设计

这一章节讲述客户端传入策略与数据库中的策略匹配的设计。你可以理解成,这一章节将重点讲述IStrategy接口中的executeStrategy()的实现。

有些同学可能就认为,就这有什么难的,我在每个策略实现类中都用业务策略.equals(请求参数)不就无敌了?如果说只有【等于】这么一种操作类型确实可以这么做,但我们有多种操作类型,不能在每个策略实现类都写一遍重复性的代码。

封装一个策略匹配工具

public class StrategyUtil {// 匹配public static boolean matchStrategy(RequestStrategyInfo requestInfo, StrategyDetail detail) {Object reqVal = null;try {reqVal = getReqVal(requestInfo, detail.getType());}return computeOper(detail.getOper(), detail.getValue(), reqVal);}// 获取请求对象中的值private Object getReqVal(RequestStrategyInfo requestInfo, String type) {// 利用反射来获取请求对象中的值,但要求策略类型的值要与RequestStrategyInfo类的属性同名Field f = RequestStrategyInfo.class.getDeclareField(type);f.setAccessible(true);return f.get(requestInfo);}// 对比值private boolean computeOper(String oper, String value, Object val) {boolean result = false;switch (oper) {case "0":result = value.equals(val);break;case "1":	// 小于result = Double.parseDouble(val) < Double.parseDouble(value);break;case "2":	// 大于result = Double.parseDouble(val) > Double.parseDouble(value);break;case "3":result = !value.equals(val);break;}return result;}
}

我们来举个城市策略的调用例子

public class CityStrategy implements IStrategy {@Overridepublic boolean executeStrategy(RequestStrategyInfo requestInfo, StrategyDetail detail) {boolean result = StrategyUtil.matchStrategy(requestInfo, detail);// 若有特殊处理操作可在此加上return result;}
}

几乎所有的策略实现类都是这样的一行代码,如果有特殊操作可以补充在后面。

与前面的选择策略实现类相结合

public class StrategyService implements InitializingBean {@Autowiredprivate ApplicationContext appContext;private Collection<IStrategy> strategys;private IStrategy strategy;private StrategyFactory strategyFactory;// 由业务类自己提供所有的策略详情public boolean executeStrategy(List<strategyDetails> strategyDetails) {// 是否支持任意策略,没有策略则说明支持所有字段if (strategyDetails.size() == 0 || strategyDetails == null) {return true;}List<Boolean> matchList = new ArrayList<>();for (StrategyDetail sd : strategyDetails) {boolean b = strategys.parallelStream().filter(it -> it.support(sd.type)).findFirst().get().executeStrategy(requestInfo, sd);matchList.add(b);}boolean b = matchList.stream().filter(it -> it == false).findFirst().orElse(null);return b == null ? true : false;}@Overridepublic void afterPropertiesSet() throws Exception() {Map<String, IStrategy> strategyMap = appContext.getBeansOfType(IStrategy.class);strategys = strategyMap.values();}
}

在业务实现类的实现思路

public class XxxServiceImpl {@Autowiredprivate StrategyService strategyServicepublic void xxx() {// 1. 处理业务......// 2. 根据业务id找出全部的关联策略详情List<StrategyDetail> strategyDetails = xxxx.getByServiceId(xx);boolean support = strategyService.executeStrategy(strategyDetails);if (support) {// 支持则进行的操作} else {// 不支持的操作}......}
}

总结

基于策略模式设计的策略命中设计,主要难点是策略模式的框架设计理念与策略值对比。

相关文章:

基于策略模式企业实战中策略命中设计

背景 在公司实际项目项目开发中&#xff0c;有一个策略命中的开发需求。根据用户请求参数的不同来动态返回不同的业务数据。比如说有城市、客户年龄、请求时间3个策略维度&#xff0c;不同的城市返回不同的地区的地标&#xff0c;根据时间地标的背景色要发生变化等等的需求。当…...

pod生命周期,pod控制器service

一&#xff1a;pod-demo.yml apiVersion: v1 # <string> kind: Pod # <string> metadata: # <Object>对象&#xff1a;键值对的集合&#xff0c;又称为映射&#xff08;mapping&#xff09;/ 哈希&#xff08;hashes&#xff09; / 字…...

SAP FICO 深入讲解会计凭证

SAP系统在数据处理&#xff0c;无论是业务处理&#xff0c;还是财务处理都会产生大量的凭证&#xff0c;无论是什么凭证&#xff0c;最终的反映形式就是 会计凭证。 1.凭证原则Code 每笔记账都一直以凭证形式存储&#xff0c;每一凭证都作为前后一致的单位保留在系统中&#xf…...

LeetCode 2341. 数组能形成多少数对

【LetMeFly】2341.数组能形成多少数对 力扣题目链接&#xff1a;https://leetcode.cn/problems/maximum-number-of-pairs-in-array/ 给你一个下标从 0 开始的整数数组 nums 。在一步操作中&#xff0c;你可以执行以下步骤&#xff1a; 从 nums 选出 两个 相等的 整数从 nums…...

PHPStorm常用快捷键

alt 1 左侧项目结构树隐藏或者显示&#xff0c;这两个组合键的使用可以切换“项目结构树”和当前打开文件之间的焦点。 alt 2 隐藏或者显示 Favorites Ctrl Shift F12 切换到最大编辑器窗口&#xff0c;隐藏其他所有的工具窗口。例如项目结构树、Favorites、Terminal等。…...

【基于腾讯云的远程机械臂小车】

【基于腾讯云的远程机械臂小车】1. 项目来源1.1 项目概述1.2 系统结构1.3 设计原理2. 硬件搭建2.1 CH32V307开发板2.2 Arduino mega25602.3 富斯I6遥控器2.4 机械臂小车2.5 ESP8266 MCU2.5.1 ESP8266 MCU介绍2.5.2 腾讯云固件烧录3. 软件设计3.1 两种控制方式3.1.1 富斯I6遥控机…...

兼职任务平台收集(一)分享给有需要的朋友们

互联网时代&#xff0c;给人们带来了很大的便利。信息交流、生活缴费、足不出户购物、便捷出行、线上医疗、线上教育等等很多。可以说&#xff0c;网络的时代会一直存在着。很多人也在互联网上赚到了第一桶金&#xff0c;这跟他们的努力和付出是息息相关的。所谓一份耕耘&#…...

MarkDown中公式的编辑

MarkDown中公式的编辑生成目录积分插入编号常见希腊字母大小写分式括号求和积分连乘根式三角函数运算符集合运算箭头逻辑运算符约等于向量绝对值申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计1077字&…...

解决jupyter以及windows系统中pycharm编译器画图的中文乱码问题大全

一、jupyter环境下中文乱码问题解决 我们在jupyter的notebook中使用matplotlib画图的时候&#xff0c;经常性的会遇见一些中文乱码显示□的情况,如下所示: 在此&#xff0c;网上给出的方法大多是以下的解决方法&#xff1a; import matplotlib.pyplot as pltplt.rcParams[fo…...

06 OpenCV 阈值处理、自适应处理与ostu方法

1 基本概念 CV2中使用阈值的作用是将灰度图像二值化&#xff0c;即将灰度图像的像素值根据一个设定的阈值分成黑白两部分。阈值处理可以用于图像分割、去除噪声、增强图像对比度等多个领域。例如&#xff0c;在物体检测和跟踪中&#xff0c;可以通过对图像进行阈值处理来提取目…...

RFC7519规范-JWT - json web token

简介 什么是JWT(JSON Web Token) 在介绍JWT之前&#xff0c;我们先来回顾一下利用token进行用户身份验证的流程&#xff1a; 客户端使用用户名和密码请求登录服务端收到请求&#xff0c;验证用户名和密码验证成功后&#xff0c;服务端会签发一个token&#xff0c;再把这个to…...

移动机器人设计与实践课程大纲

MiR移动机器人参考资料&#xff1a;图一 西北工业大学-课程平台图二 清华大学出版社-移动机器人目前&#xff0c;基本都是双一流大学开设此类课程&#xff0c;并且都是至少3-4学分&#xff0c;16学时/学分&#xff0c;48-64学时。(⊙﹏⊙)&#xff0c;难办了。咱这只有&#xf…...

Lesson 7.2 Mini Batch K-Means与DBSCAN密度聚类

文章目录一、Mini Batch K-Means 算法原理与实现二、DBSCAN 密度聚类基本原理与实践1. K-Means 聚类算法的算法特性2. DBSCAN 密度聚类基本原理3. DBSCAN 密度聚类的 sklearn 实现除了 K-Means 快速聚类意外&#xff0c;还有两种常用的聚类算法。&#xff08;1&#xff09; 是能…...

11.Dockerfile最佳实践

Dockerfile 最佳实践 Docker官方关于Dockerfile最佳实践原文链接地址&#xff1a;https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ Docker 可以通过从 Dockerfile 包含所有命令的文本文件中读取指令自动构建镜像&#xff0c;以便构建给定镜像。 …...

【企业云端全栈开发实践-1】项目介绍及环境准备、Spring Boot快速上手

本节目录一、 项目内容介绍二、Maven介绍2.1 Maven作用2.2 Maven依赖2.3 本地仓库配置三、Spring Boot快速上手3.1 Spring Boot特点3.2 遇到的Bug&#xff1a;spring-boot-maven-plugin3.3 遇到的Bug2&#xff1a;找不到Getmapping四、开发环境热部署一、 项目内容介绍 本课程…...

5-HT2A靶向药物|适应症|市场销售-上市药品前景分析

据世界卫生组织称&#xff0c;抑郁症是一种多因素疾病&#xff0c;影响全球约3.5 亿人。中枢神经系统最广泛的单胺 - 血清素 (5-HT) 被认为在这种情况的病理机制中起着至关重要的作用&#xff0c;并且神经递质的重要性被“血清素假说”提升&#xff0c;将抑郁症的存在联系起来 …...

HTTPS协议原理---详解

目录 一、HTTPS 1.加密与解密 2.我们为什么要加密&#xff1f; 3.常见加密方式 ①对称加密 ②非对称加密 4.数据摘要 5.数字签名 二、HTTPS的加密方案 1.只是用对称加密​ 2.只使用非对称加密 3.双方都使用非对称加密 4.非对称加密&#xff0b;对称加密 中间人攻…...

Pytest学习笔记

Pytest学习笔记 1、介绍 1.1、单元测试 单元测试是指在软件开发当中&#xff0c;针对软件的最小单位&#xff08;函数&#xff0c;方法&#xff09;进行正确性的检查测试 1.2、单元测试框架 测试发现&#xff1a;从多个py文件里面去找到我们测试用例测试执行&#xff1a;按…...

Fuzz概述

文章目录AFL一些概念插桩与覆盖率边和块覆盖率afl自实现劫持汇编器clang内置覆盖率反馈与引导变异遗传算法fork server机制AFL调试准备AFL一些概念 插桩与覆盖率 边和块 首先&#xff0c;要明白边和块的定义 正方形的就是块&#xff0c;箭头表示边&#xff0c;边表示程序执行…...

区块链知识系列 - 系统学习EVM(四)-zkEVM

区块链知识系列 - 系统学习EVM(一) 区块链知识系列 - 系统学习EVM(二) 区块链知识系列 - 系统学习EVM(三) 今天我们来聊聊 zkEVM、EVM 兼容性 和 Rollup 是什么&#xff1f; 1. 什么是 Rollup rollup顾名思义&#xff0c;就是把一堆交易卷&#xff08;rollup&#xff09;起来…...

Leetcode.2341 数组能形成多少数对

题目链接 Leetcode.2341 数组能形成多少数对 Rating : 1185 题目描述 给你一个下标从 0 开始的整数数组 nums。在一步操作中&#xff0c;你可以执行以下步骤&#xff1a; 从 nums选出 两个 相等的 整数从 nums中移除这两个整数&#xff0c;形成一个 数对 请你在 nums上多次执…...

C++复习笔记10

1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 2. list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素。 3. list与for…...

leaflet 纯CSS的marker标记,不用图片来表示(072)

第072个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中使用纯CSS来打造marker的标记。这里用到的是L.divIcon来引用CSS来构造新icon,然后在marker的属性中引用。 这里必须要注意的是css需要是全局性质的,不能被scoped转义为其他随机的css。 直接复制下面的 v…...

Elasticsearch:使用 intervals query - 根据匹配项的顺序和接近度返回文档

Intervals query 根据匹配项的顺序和接近度返回文档。Intervals 查询使用匹配规则&#xff0c;由一小组定义构成。 然后将这些规则应用于指定字段中的术语。 这些定义产生跨越文本正文中的术语的最小间隔序列。 这些间隔可以通过父源进一步组合和过滤。 上述描述有点费解。我…...

无法决定博客主题的人必看!如何选择类型和推荐的 5 种选择

是否有人不能迈出第一步&#xff0c;因为博客的类型还没有决定&#xff1f;有些人在出发时应该行动&#xff0c;而不是思考&#xff0c;但让我们冷静下来&#xff0c;仔细想想。博客的难度因流派而异&#xff0c;这在很大程度上决定了随后的发展。因此&#xff0c;在选择博客流…...

数字化转型的成功模版,珠宝龙头曼卡龙做对了什么?

2月11日&#xff0c;曼卡龙&#xff08;300945.SZ&#xff09;发布2022年业绩快报&#xff0c;报告期内&#xff0c;公司实现营业收入16.11亿元&#xff0c;同比增长28.63%。来源&#xff1a;曼卡龙2022年度业绩快报曼卡龙能在2022年实现营收增长尤为不易。2022年受疫情影响&am…...

转换矩阵、平移矩阵、旋转矩阵关系以及python实现旋转矩阵、四元数、欧拉角之间转换

文章目录1. 转换矩阵、平移矩阵、旋转矩阵之间的关系2. 缩放变换、平移变换和旋转变换2. python实现旋转矩阵、四元数、欧拉角互相转化由于在平时总是或多或少的遇到平移旋转的问题&#xff0c;每次都是现查资料&#xff0c;然后查了忘&#xff0c;忘了继续查&#xff0c;这次弄…...

中国地图航线图(echarjs)

1、以上为效果图 需要jq、echarjs、china.json三个文件支持。以上 2、具体代码 DOM部分 <!-- 服务范围 GO--> <div class"m-maps"><div id"main" style"width:1400px;height: 800px; margin: 0 auto;"> </div> <!-…...

Python正则表达式中group与groups的用法详解

本文主要介绍了Python正则表达式中group与groups的用法详解&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值&#xff0c;需要的朋友们下面随着小编来一起学习学习吧目录在Python中&#xff0c;正则表达式的group和groups方…...

c++练习题7

1&#xff0e;下列运算符中优先级最高的是 A&#xff09;> B&#xff09; C&#xff09; && D&#xff09;! 2&#xff0e;以下关于运算符优先级的描述中&#xff0c;正确的是 。 A&#xff09;!&#xff08;逻辑非&#x…...

做b2c网站/童程童美少儿编程怎样收费

最近这几年购置的电脑几乎都安装了Windows 10&#xff0c;并且使用UEFI方式启动(UEFI即统一可扩展固件接口&#xff0c;用来定义操作系统与固件之间的软件界面&#xff0c;作为BIOS的替代方案)。UEFI启动和传统的BIOS启动不同&#xff0c;它不再支持实模式启动系统如DOS等。而传…...

怎么用adobe软件做网站/微信引流主动被加软件

本节书摘来自异步社区《深入解析IPv6&#xff08;第3版&#xff09;》一书中的第1章&#xff0c;第1.2节,作者&#xff1a; 【美】Joseph Davies 更多章节内容可以访问云栖社区“异步社区”公众号查看。 1.2 IPv4地址空间受限的后果 由于IPv4的地址相对比较稀缺&#xff0c;人…...

网站建站对象/快速搭建网站的工具

K-means聚类算法(事先数据并没有类别之分&#xff01;所有的数据都是一样的)1、概述K-means算法是集简单和经典于一身的基于距离的聚类算法采用距离作为相似性的评价指标&#xff0c;即认为两个对象的距离越近&#xff0c;其相似度就越大。该算法认为类簇是由距离靠近的对象组成…...

asp access 手机站 用于做微网站/苏州网络公司

PR劫持的定义和方法2018-03-19传承网络次什么是PR劫持&#xff1f;一般搜索引擎在处理301和302转向的时候&#xff0c;都是把目标URL当作实际应该收录的URL。当然也有特例&#xff0c;不过在大部分情况下是这样处理的。所以如果你从域名A做301或302跳转到域名B&#xff0c;而域…...

宁波怎么做网站排名优化/永久免费自助建站系统

传输层的作用&#xff1a;1.保证可靠传输 2.流量控制 往返时间RTT UDP(User Datagram Protocol)是一种无连接的数据传输的协议 TCP (Transmission Control Protocol)是一种面向连接的传输协议 传输控制协议&#xff1a; 1.停等协议 细节&#xff1a;收到ACK之后再发送下一个数据…...

用苹果cms做电影网站/最好的免费信息发布平台

需求&#xff1a; python代码实现 1. 按层打印二叉树 2. 需要打印二叉树层与层之间的斜线 3. 结点的下一层如果没有子节点&#xff0c;以‘N’代替 方法&#xff1a; 使用namedtuple表示二叉树使用StringIO方法&#xff0c;遍历时写入结果&#xff0c;最后打印出结果打印…...