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

设计模式:详细拆解策略模式

策略模式

既然是详解,就不以案例开头了,直奔主题,先来看看什么是策略模式。

模式定义

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式 使得算法可独立于使用它的客户而变化。

结构

Strategy(策略接口):

  • 用来约束一系列具体的策略算法。
  • 定义了算法的公共接口,使得算法可以互换使用。

ConcreteStrategy(具体策略实现)

  • 具体的算法实现,继承自策略接口。
  • 每个具体策略类实现了策略接口中定义的算法

Context(上下文):

  • 负责和具体的策略类交互。
  • 通常上下文会持有一个真正的策略实现。
  • 上下文可以让具体的策略类来获取上下文的数据。
  • 甚至可以让具体的策略类来回调上下文的方法。

样例代码:

// 策略接口
interface Strategy {void algorithmInterface();
}// 具体策略A
class ConcreteStrategyA implements Strategy {@Overridepublic void algorithmInterface() {System.out.println("执行策略A的算法实现");}
}// 具体策略B
class ConcreteStrategyB implements Strategy {@Overridepublic void algorithmInterface() {System.out.println("执行策略B的算法实现");}
}// 具体策略C
class ConcreteStrategyC implements Strategy {@Overridepublic void algorithmInterface() {System.out.println("执行策略C的算法实现");}
}// 上下文类
class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public void setStrategy(Strategy strategy) {this.strategy = strategy;}public void contextInterface() {strategy.algorithmInterface();}
}// 客户端代码
public class StrategyPatternDemo {public static void main(String[] args) {Context context = new Context(new ConcreteStrategyA());context.contextInterface();context.setStrategy(new ConcreteStrategyB());context.contextInterface();context.setStrategy(new ConcreteStrategyC());context.contextInterface();}
}

策略模式实现案例

我们以CRM中的报价场景为例,来看一下策略模式的使用,简化一下场景,会有如下的报价方案:

  • 对普通客户或者是新客户报全价:
  • 对老客户报的价格,统一折扣5%;
  • 对大客户报的价格,统一折扣10%。

根据策略模式的思路,我们大致要做如下内容:

  1. 首先需要定义出算法的接口。
  2. 然后把各种报价的计算方式单独出来,形成算法类。
  3. 对于Price类,把它当做上下文,在计算报价的时候,不再需要判断,直接使 用持有的具体算法进行运算即可。具体选择使用哪一个算法的功能挪出去,放到外部使 用的客户端去。

策略模式形成的类图如下:

基于SpringBoot的项目实现

// 策略接口
public interface Strategy {double calcPrice(double goodsPrice);
}// 普通客户策略
@Commpont
public class NormalCustomerStrategy implements Strategy {@Overridepublic double calcPrice(double goodsPrice) {// 普通客户不打折return goodsPrice;}
}// 老客户策略
@Commpont
public class OldCustomerStrategy implements Strategy {@Overridepublic double calcPrice(double goodsPrice) {// 老客户享受5%的折扣return goodsPrice * 0.95;}
}// 大客户策略
@Commpont
public class LargeCustomerStrategy implements Strategy {@Overridepublic double calcPrice(double goodsPrice) {// 大客户享受10%的折扣return goodsPrice * 0.90;}
}// 报价上下文类
public class Price {private Strategy strategy;// 构造函数,初始化策略public Price(Strategy strategy) {this.strategy = strategy;}// 设置策略public void setStrategy(Strategy strategy) {this.strategy = strategy;}// 计算并返回报价public double quote(double goodsPrice) {return strategy.calcPrice(goodsPrice);}
}public enum ClientType{//正常客户normal,//老客户old,//大客户large;}@Service
public class ClientServiceImpl implement ClientService{@Autowired
private ApplicationContext context;//……public ResData createQutePrice(String clientId){ResData result = new ResData();Client client = ClientMapper.findById(clientId);//……客户其他认证逻辑Double nowPrice = XXMapper.queryNowPrice();result.setPrice(getPriceUtil(client.getClientType()).qute(nowPrice ));return result;
}private Price getPriceUtil(ClientType type){Strategy strategy = null; switch(type){case old:strategy = (Strategy)context.getBean(OldCustomerStrategy.class);break;case large:strategy = (Strategy)context.getBean(LargeCustomerStrategy.class);break;default:strategy = (Strategy)context.getBean(NormalCustomerStrategy.class);break;}Price price = new Price(strategy);return price;
}}

使用该写法,虽然相比if-else来讲要更为麻烦,但是随着报价场景的增加,我们仅仅通过新增实现类和调整getPriceUtil方法即可完成扩展。

策略模式详解

策略模式的本质

策略模式的本质是:

分离算法,选择实现

策略模式的功能是把具体的算法实现从具体的业务处理中独立出来,把它们实现成 为单独的算法类,从而形成一系列的算法,并让这些算法可以相互替换。 策略模式的重心不是如何来实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。

策略模式一个很大的特点就是各个策略算法的平等性。对于一系列具体的策略算法, 大家的地位是完全一样的,正是因为这个平等性,才能实现算法之间可以相互替换。 所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。 所以可以这样描述这一系列策略算法:策略算法是相同行为的不同实现。

从设计原则角度

  • 策略模式很好地体现了开一闭原则。策略模式通过把一系列可变的算法进行封装,并定义出合理的使用结构,使得在系统出现新算法的时候,能够很容易地把新的算法加入到已有的系统中,而已有的实现不需要做任何修改。这在前面的示例中已经体现出来了,好好体会一下。
  • 策略模式还很好地体现了里氏替换原则。策略模式是一个扁平结构,一系列的实现算法其实是兄弟关系,都是实现同一个接口或者继承的同一个父类。这样只要使用策略的客户保持面向抽象类型编程,就能够使用不同策略的具体实现对象来配置它,从而实现一系列算法可以相互替换。

策略模式与If-else

看了前面的示例,很多朋友会发现,每个策略算法具体实现的功能,就是原来在f-else 结构中的具体实现。 没错,其实多个if-elseif语句表达的就是一个平等的功能结构,你要么执行if,要么 执行else,或者是elseif,这个时候,if块中的实现和else块中的实现从运行地位上来讲是平等的。 而策略模式就是把各个平等的具体实现封装到单独的策略实现类了,然后通过上下 文来与具体的策略类进行交互。所以其实很多地方都在讲策略模式能消除遍地if-else是不准确的,if-else并没有消失,只是代码形式改变了,但是使用策略模式替换if-else的优势是不可否认的,将原本if-else内的逻辑抽离出来,可以达到修改具体内容而不破坏外层框架的目的。因此多个f-else语句可以考虑使用策略模式。

Strategy的扩展

在前面的示例中,Strategy都是使用接口来定义的,这也是常见的实现方式。但是如 果多个算法具有公共功能的话,可以把Strategy实现成为抽象类,然后把多个算法的公 共功能实现到Strategy中。

// 抽象策略类,包含公共功能
public abstract class Strategy {// 公共方法,所有策略类都会用到public void commonMethod() {System.out.println("这是一个公共方法");}// 抽象方法,具体的策略算法实现public abstract void algorithmInterface();
}// 具体策略A
public class ConcreteStrategyA extends Strategy {@Overridepublic void algorithmInterface() {System.out.println("执行策略A的算法实现");}
}// 具体策略B
public class ConcreteStrategyB extends Strategy {@Overridepublic void algorithmInterface() {System.out.println("执行策略B的算法实现");}
}// 具体策略C
public class ConcreteStrategyC extends Strategy {@Overridepublic void algorithmInterface() {System.out.println("执行策略C的算法实现");}
}

Context与Strategy的关系

在策略模式中,通常是上下文(Context)使用具体的策略实现对象。反过来,策略实现对象也 可以从上下文获取所需要的数据。因此可以将上下文当作参数传递给策略实现对象,这 种情况下上下文和策略实现对象是紧密耦合的。 在这种情况下,上下文封装看具体策略对象进行算法运算所需要的数据,具体策略 对象通过回调上下文的方法来获取这些数据。 甚至在某些情况下,策略实现对象还可以回调上下文的方法来实现一定的功能,这种使用场景下,上下文变相充当了多个策略算法实现的公共接口。在上下文定义的方法 可以当作是所有或者是部分策略算法使用的公共功能。

但是需要注意,由于所有的策略实现对象都实现同一个策略接口,传入同一个上 下文,可能会造成传入的上下文数据的浪费,因为有的算法会使用这些数据, 而有的算法不会使用,但是上下文和策略对象之间交互的开销是存在的。

以一个公司结算的场景案例来说:

很多企业的工资支付方式是很灵活的,可支付方式是比较多的,比如,人民币现金支付、美元现金支付、银行转账到工资账户、银行转账到工资卡;一些创业型的企业为了留住骨干员工,还可能有工资转股权等方式。总之一句话,工资支付方式很多。

随着公司的发展,会不断有新的工资支付方式出现,这就要求能方便地扩展;另外工资支付方式不是固定的,是由公司和员工协商确定的,也就是说可能不同的员工采用的是不同的支付方式,甚至同一个员工,不同时间采用的支付方式也可能会不同,这就要求能很方便地切换具体的支付方式。

要实现这样的功能,显然策略模式是一个很好的选择。在实现这个功能的时候,不同的策略算法需要的数据是不一样,比如,现金支付就不需要银行账号,而银行转账就需要账号。

这就导致在设计策略接口中的方法时,不太好确定参数的个数,而且,就算现在把所有的参数都列上了,扩展性难以保障,加入一个新策略,就需要修改接口。我们根据上面对于Context与Strategy的关系分析,基于将上下文当作参数传递给策略对象的方式以策略模式实现上述需求

先定义工资支付的策略接口,也就是定义一个支付工资的方法:

/*** 支付工资的策略接口,公司有多种支付工资的算法* 比如,现金、银行卡、现金加股票、现金加期权、美元支付等*/
public interface PaymentStrategy {/*** 公司给某人真正支付工资* @param ctx 支付工资的上下文,里面包含算法需要的数据*/public void pay(PaymentContext ctx);
}

这里先简单实现人民币现金支付和美元现金支付方式,当然并不是真地去实现跟银行的交互,只是示意一下:

/*** 人民币现金支付*/
public class RMBCash implements PaymentStrategy {public void pay(PaymentContext ctx) {System.out.println("现在给" + ctx.getUserName() + "人民币现金支付" + ctx.getMoney() + "元");}
}/*** 美元现金支付*/
public class DollarCash implements PaymentStrategy {public void pay(PaymentContext ctx) {System.out.println("现在给" + ctx.getUserName() + "美元现金支付" + ctx.getMoney() + "元");}
}

 下面是上下文的实现以及使用:

/*** 支付工资的上下文,每个人的工资不同,支付方式也不同*/
public class PaymentContext {/*** 应被支付工资的人员,简单点,用姓名来代替*/private String userName = null;/*** 应被支付的工资金额*/private double money = 0.0;/*** 支付工资的方式的策略接口*/private PaymentStrategy strategy = null;// 构造方法,传入被支付工资的人员,应支付的金额和具体的支付策略// @param userName 被支付工资的人员// @param money 应支付的金额// @param strategy 具体的支付策略public PaymentContext(String userName, double money, PaymentStrategy strategy) {this.userName = userName;this.money = money;this.strategy = strategy;}// 只有getter方法,让策略算法在实现的时候,根据需要来获取上下文中的数据public String getUserName() {return userName;}public double getMoney() {return money;}/*** 立即支付工资*/public void payNow() {// 使用客户希望的支付策略来支付工资this.strategy.pay(this);}
}public class Client {public static void main(String[] args) {// 创建相应的支付策略PaymentStrategy strategyRMB = new RMBCash();PaymentStrategy strategyDollar = new DollarCash();// 准备小李的支付工资上下文PaymentContext ctx1 = new PaymentContext("小李", 5000, strategyRMB);// 向小李支付工资ctx1.payNow();// 切换一个人,给Petter支付工资PaymentContext ctx2 = new PaymentContext("Petter", 8000, strategyDollar);ctx2.payNow();}
}

基本的策略模式框架已经搭建完成,如果接下来需要增加一种支付方式,要求能支付到银行,基于以上代码,扩展方式有两种。

扩展方式一:通过扩展上下文对象(Context)来准备新的算法需要的数据

/*** 扩展的支付上下文对象*/
public class PaymentContext2 extends PaymentContext {/*** 银行账号*/private String account = null;/*** 构造方法,传入被支付工资的人员,应支付的金额和具体的支付策略* @param userName 被支付工资的人员* @param money 应支付的金额* @param account 支付到的银行账号* @param strategy 具体的支付策略*/public PaymentContext2(String userName, double money, String account, PaymentStrategy strategy) {super(userName, money, strategy);this.account = account;}public String getAccount() {return account;}
}/*** 算法策略的实现* 支付到银行卡*/
public class Card implements PaymentStrategy {public void pay(PaymentContext ctx) {// 这个新的算法自己知道要使用扩展的支付上下文,所以强制造型一下PaymentContext2 ctx2 = (PaymentContext2) ctx;System.out.println("现在给" + ctx2.getUserName() + "的"+ ctx2.getAccount() + "账号支付了" + ctx2.getMoney() + "元");// 连接银行,进行转账,就不去管了}
}public class Client {public static void main(String[] args) {// 创建相应的支付策略PaymentStrategy strategyRMB = new RMBCash();PaymentStrategy strategyDollar = new DollarCash();// 准备小李的支付工资上下文PaymentContext ctx1 = new PaymentContext("小李", 5000, strategyRMB);// 向小李支付工资ctx1.payNow();// 切换一个人,给Petter支付工资PaymentContext ctx2 = new PaymentContext("Petter", 8000, strategyDollar);ctx2.payNow();// 测试新添加的支付方式PaymentStrategy strategyCard = new Card();PaymentContext2 ctx3 = new PaymentContext2("小王", 9000, "010998877656", strategyCard);ctx3.payNow();}
}

 通过代码实现,可以看出,这种扩展方式是新增加一种支付到银行卡的策略实现,然后通过继承来扩展支付上下文,其中添加新的支付方式需要的新数据,比如银行卡账户,并在客户端使便用新的上下文和新的策略实现就可以了,这样已有的实现都不需要改变,完全遵循开一闭原则。

扩展方式二:通过策略的构造方法传入新算法所需数据 

/*** 支付到银行卡*/
public class Card2 implements PaymentStrategy {// 账号信息private String account = "";/*** 构造方法,传入账号信息* @param account 账号信息*/public Card2(String account) {this.account = account;}public void pay(PaymentContext ctx) {System.out.println("现在给" + ctx.getUserName() + "的"+ this.account + "账号支付了" + ctx.getMoney() + "元");// 连接银行,进行转账,就不去管了}
}// 直接在客户端测试就可以了。示例代码如下:
public class Client {public static void main(String[] args) {// 测试新添加的支付方式PaymentStrategy strategyCard2 = new Card2("010998877656");PaymentContext ctx4 = new PaymentContext("小", 9000, strategyCard2);ctx4.payNow();}
}

 

  • 对于扩展上下文的方式:

    • 优点:所有策略的实现风格更统一,策略需要的数据都统一从上下文来获取,这样在使用方法上也很统一;在上下文中添加新的数据,别的相应算法也可以用得上,可以视为公共的数据。
    • 缺点:如果这些数据只有一个特定的算法来使用,那么这些数据有些浪费;每次添加新的算法都去扩展上下文,容易形成复杂的上下文对象层次,也未见得有必要。
  • 对于在策略算法的实现上添加自己需要的数据的方式:

    • 优点:实现起来简单,容易理解。
    • 缺点:实现风格与其他策略不一致,其他策略都是从上下文中来获取数据,而这个策略的实现一部分数据来自上下文,一部分数据来自自己,有些不统一;外部使用这些策略算法的时候也不一,难于以一个统一的方式来动态切换策略算法。

适用策略模式的场景

  1. 当出现有许多相关的类,仅仅是行为有差别的情况下,可以使用策略模式来使用多个行为中的一个来配置一个类的方法,实现算法动态切换。

  2. 当出现同一个算法,有很多不同实现的情况下,可以使用策略模式来把这些“不同的实现”实现成为一个算法的类层次。

  3. 当需要封装算法中,有与算法相关数据的情况下,可以使用策略模式来避免暴露这些跟算法相关的数据结构。

  4. 当出现抽象一个定义了很多行为的类,并且是通过多个f-else语句来选择这些行为的情况下,可以使用策略模式来代替这些条件语句。

相关文章:

设计模式:详细拆解策略模式

策略模式 既然是详解,就不以案例开头了,直奔主题,先来看看什么是策略模式。 模式定义 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式 使得算法可独立于使用它的客户而变化。 结构 Strategy&a…...

Python正则表达式面试题分析总结

Python正则表达式面试题主要围绕Python内置的re模块展开,考察的是应聘者对于正则表达式的理解、使用以及在实际问题中的应用能力。以下是对这些面试题的详细分析总结: 正则表达式基础: re模块简介:Python中的re模块提供了正则表达…...

LeetCode题练习与总结:超过经理收入的员工--181

一、题目描述 SQL Schema > Pandas Schema > 表:Employee ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | | salary | int | | managerId | int | ----…...

LInux:循环语句

LInux:循环语句 if-else语句 if 语句语法格式 if [ $a -gt $b ]; then echo "a>b" fiif [ $a -gt $b ]; then echo "a>b"echo "a!b"echo "true" fiif-else语句 if-else 语句语法格式 if [ $a -gt $b ]; then echo &q…...

NumPy和Pandas中的布尔索引

布尔索引(Boolean Indexing)是数据分析中一种强大且常用的技术,用于通过布尔值数组(即包含 True 和 False 的数组)来选择数据子集。布尔索引可以用于 NumPy 数组、Pandas 数据框等数据结构。 布尔索引是一种非常有用的…...

.NET 一款反序列化打入冰蝎内存马的工具

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…...

FPGA实现SDI视频接收转USB3.0传输,GS2971+FT601方案,提供4套工程源码和QT上位机源码

目录 1、前言工程概述免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本博已有的FPGA驱动USB通信方案FPGA基于GS2971的SDI视频解码方案FPGA基于FT601的USB3.0视频传输方案 3、详细设计方案设计原理框图SDI 相机GS2971-SDI解码芯片解读BT1120转RGB888图像缓存FT601-USB3.0芯…...

2024第26届中国(深圳)国际清洁能源、储能科技与新型电力展览会

源网荷储充产业链盛会,2024年续写辉煌,第26届中国国际清洁能源、储能技术与新型电力展览会11月11日将启幕; 2024第二十六届中国国际储能技术与设备展览会 China International Energy Storage Technology and Equipment Exhibition 2024第二…...

计算机基础(Windows 10+Office 2016)教程 —— 第6章 电子表格软件Excel 2016(下)

电子表格软件Excel 2016 6.4 Excel 2016的公式与函数6.4.1 公式的概念6.4.2 公式的使用6.4.3 单元格的引用6.4.4 函数的使用6.4.5 快速计算与自动求和 6.5 Excel 2016的数据管理6.5.1 数据排序6.5.2 数据筛选6.5.3 分类汇总6.5.4 分组显示6.5.5 合并计算 6.6 Excel 2016的图表6…...

npm install 巨慢,导致Jenkins编译报错问题解决——基础积累

今天在弄后台系统的服务器编译时,一直报错。报错信息为:系统找不到指定的路径。 最后进入到服务器中,找到E:/Jenkins/WorkSpace/JiePeiAiMomsAdmin_FenZhi这个路径,然后通过cmd进入到命令提示符中。 然后通过npm i进行安装&#…...

Stable Diffusion 使用详解(5)---- 光影效果与场景融入

目录 背景 底模选取 提示词 ControlNet openpose illumination 效果 背景 有一家服装品牌店,需要绘制一款模特穿着某个英文LOG的漂亮服装,这是一种很常见UI作画需求,这类需求实际上可以透过选取正确的底模 controlNet 进行完美的实现…...

5G三大场景:eMBB、mMTC、uRLLC

1G,2G,3G,4G,5G有什么区别?5G的优势在哪?有什么应用? 1G,2G,3G,4G,5G有什么区别?5G的优势在哪?有什么应用?_3g4g5g的区别和作用-CSDN博客 从1G到4G,移动通信的核心是人与人之间的通信&#xff0…...

数据结构(面试)

目录 线索二叉树哈夫曼树并查集最小生成树最短路径拓扑排序二叉排序树平衡二叉树红黑树折半查找散列表堆排序归并排序 线索二叉树 原理:利用树节点的n1个左右空指针指向其遍历序列的前驱和后继(线索) 优点:简化遍历,不…...

从“人巡”到“智控”:EasyCVR智能视频监控技术变革河道违建监测模式

一、背景分析 随着城市化进程的加快,河道作为城市生态系统的重要组成部分,其保护与管理日益受到重视。然而,非法侵占河道、违规建设等行为时有发生,不仅破坏了河道的自然生态,还严重威胁到防洪安全和水质安全。为了有…...

JAVA基础 - 反射

目录 一. 简介 二. java.lang.Class类 三. java.lang.reflect包 四. 创建对象 五. 调用方法 六. 调用成员变量 一. 简介 反射是 Java 语言中的一种强大机制,允许程序在运行时动态地获取类的信息、访问类的成员(包括字段、方法和构造函数&#xff…...

【系统架构设计师】二十二、嵌入式系统架构设计理论与实践③

目录 一、鸿蒙操作系统架构案例分析 1.1 鸿蒙操作系统定义 1.2 鸿蒙的层次化分析 1.2.1 内核层 1.2.2 系统服务层 1.2.3 框架层 1.2.4 应用层 1.3 鸿蒙操作系统的架构分析 1.3.1 鸿蒙操作系统架构具有4个技术特性 1.3.2 分布式架构所带来的优势 1.3.3 HarmonyOS 架构…...

【轨物推荐】经济长波:创新周期的历史

原创 丑丑姐姐 专利分析可视化 2021年08月01日 21:18 图片来源:Visual Capitalist 在开始本文之前,我们先来学习两个概念: 经济长波(Long Waves),亦称“大循环理论”、“康德拉季耶夫周期”。经济长波理论…...

springboot高校勤工俭学平台-计算机毕业设计源码66824

摘 要 本研究基于Spring Boot企业框架,设计并实现了一款高校勤工俭学平台,包括首页、通知公告、新闻通知和岗位信息等功能模块。该平台旨在为高校学生提供便捷的勤工俭学信息发布与查询服务,促进校园内部劳动力资源的充分利用和高效管理。在研…...

CRM是什么?如何用CRM管理好客户?

在企业的销售运营中,客户是是贯穿始终的主体。客户的需求、偏好与满意度,指引着企业未来改变、优化的方向。而企业销售运营的核心,就是“客户至上”。 面对庞杂的客户信息,如何快速高效的进行客户管理呢?那就是要有一…...

编程入门:大学新生的指南与策略

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

Spring Cloud中怎么使用Resilience4j Retry对OpenFeign进行重试

在微服务架构中,服务之间的通信是非常频繁的。而使用OpenFeign可以极大简化微服务之间的HTTP通信。但在复杂的分布式系统中,服务之间的调用可能会因为网络问题、服务故障等原因而失败。因此,实现服务调用的重试机制显得尤为重要。Resilience4…...

【Redis 进阶】事务

Redis 的事务和 MySQL 的事务概念上是类似的,都是把一系列操作绑定成一组,让这一组能够批量执行。 一、Redis 的事务和 MySQL 事务的区别 1、MySQL 事务 原子性:把多个操作打包成一个整体。(要么全都做,要么都不做&am…...

Linux的防火墙

一、防火墙概述 防火墙是一种计算机硬件和软件的结合,使internet和intranet之间建立一个安全网关(Security Gateway),从而保护内网免受非法用户侵入的技术。 防火墙主要由服务访问规则、验证工具、包过滤和应用网关4个部分组成。…...

跟张良均老师学大数据人工智能-批量集训营开班中

随着我国大数据和人工智能产业的飞速发展,未来社会对高素质科技人才的需求日益旺盛。为助力广大青少年提前掌握前沿技术,实现自我价值,泰迪智能科技多名优秀老师联合打造暑期大数据人工智能集训营,旨在培养具备创新精神和实战能力…...

2024年音频剪辑必备:五大最佳音频编辑软件精选!

在数字时代,音频剪辑已成为创意表达的重要工具。无论是音乐制作、播客编辑还是视频后期,一款优秀的音频剪辑软件都是不可或缺的。推荐五款备受推崇的音频剪辑工具。 福昕音频剪辑 链接:https://www.foxitsoftware.cn/audio-clip/ 福昕音频…...

Native Programs(本机程序)

Native Programs System Program(系统程序)Config ProgramStake ProgramVote ProgramAddress Lookup Table ProgramBPF LoaderEd25519 ProgramSecp256k1 Program Solana contains a small handful of native programs that are part of the validator im…...

RisingWave 1.10 发布!新增用户自定义聚合函数

我们非常高兴地宣布:RisingWave 1.10 版本正式发布!新版本为大家带来了许多重要更新,例如:新增用户自定义聚合函数 (UDAF)、支持从游标获取多个更新、支持可溢出哈希 Join、增强 CDC 连接器、新增 Sink 连接器等。一起来了解本次更…...

Modbus通讯协议

Modbus通讯协议 Modbus协议是一种用于电子控制器之间的通信协议,‌它允许不同类型的设备之间进行通信,‌以便进行数据交换和控制。‌Modbus协议最初为可编程逻辑控制器(‌PLC)‌通信开发,‌现已广泛应用于工业自动化领…...

fal.ai发布超分辨率模型——AuraSR V2

今天,我们发布了单步 GAN 升频器的第二个版本: AuraSR。 我们在上个月发布了 AuraSR v1,社区的反响让我们深受鼓舞,因此我们立即开始了新版本的训练。 AuraSR 基于 Adobe Gigagan 论文,以 lucidrain 的实现为起点。Gi…...

SYD88xx代码复位不成功和解决办法

原来的复位代码如下: void ota_manage(void){#ifdef _OTA_if(ota_state){switch(ota_state){case 1 : #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)dbg_printf("start FwErase\r\n");#endifCmdFwErase();#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)db…...

怎样自己做网站推广/seo技术分享

教育 -金融工程学-新-章节资料考试资料-宁波财经学院【】 1.1 随堂测试 1、【多选题】从交易层面来看,属于零和游戏的有: A、股票 B、期货 C、期权 D、互换 参考资料【 】 2、【判断题】远期合约出现的比期货合约早。 A、正确 B、错误 参考资料【 】 3、…...

上海公司注册网/网站排名优化培训课程

转自:http://dev.10086.cn/cmdn/wiki/index.php?doc-view-3717.htmlAndroidSDK提供了一个强大的类Drawable,Drawable这个抽象类到底代表了什么,如何使用?Drawable是个很抽象的概念,通过简单的例子程 序来学习它&#…...

龙岩网站建设哪里比较好/手机怎么建自己的网站

1 java socket的两个timeout 一个是connect timeout,即建立连接的timeout,另外一个是so timeout,是读取数据的timeout。这两个timeout都是因为客户端等不及了。 2 connect timeout 客户端想要和服务器端建立tcp连接,如果连接迟迟没…...

内贸在什么网站做/石家庄限号

支付宝沙箱环境支付demo 下载电脑网站的官方demo: 下载地址:https://docs.open.alipay.com/270/106291/ 解压导入demo项目 3.配置AlipayConfig 3.1 注册蚂蚁金服开发者账号 注册地址:https://open.alipay.com/platform/home.htm &#xff…...

网站 图标 素材/百度pc网页版登录入口

通过代码来实现判断每一个左括号是否都有与他能正确对应的右括号。 例子:( ( ) ( ( ) ) ( ) ) 我们可以通过观察发现,当出现第一个右括号的时候和他正确对应的左括号就是在他只出现之前的最后一个左括号,那么我们可以根据栈的(后进…...

南阳企业网站建设/什么是网站推广?

一、基本思想: 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小, 然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变…...