万字解析设计模式之策略模式、命令模式

一、策略模式

1.1概述

先看下面的图片,我们去旅游选择出行模式有很多种,可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。

 策略模式(Strategy Pattern)是一个行为型设计模式,它定义了一组算法家族,分别封装起来,让它们之间可以互相替换,且算法的变化不会影响使用算法的客户。通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

1.2结构

策略模式的主要角色如下:

  • 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。定义了所有支持的算法的共同接口,可以是抽象类、接口或抽象类和接口的组合。
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。
  • 环境(Context)类:持有一个策略类的引用,将具体的算法委托给这些策略对象来处理,最终给客户端调用。

1.3实现

【例】促销活动

一家百货公司在定年度的促销活动。针对不同的节日(春节、中秋节、圣诞节)推出不同的促销活动,由促销员将促销活动展示给客户。类图如下:

 抽象策略(Strategy)类

package com.yanyu.Strategyer;public interface Strategy {void show();
}

具体策略角色(Concrete Strategy)

package com.yanyu.Strategyer;//为春节准备的促销活动A
public class StrategyA implements Strategy {public void show() {System.out.println("买一送一");}
}
package com.yanyu.Strategyer;//为中秋准备的促销活动B
public class StrategyB implements Strategy {public void show() {System.out.println("满200元减50元");}
}
package com.yanyu.Strategyer;//为圣诞准备的促销活动C
public class StrategyC implements Strategy {public void show() {System.out.println("满1000元加一元换购任意200元以下商品");}
}

环境(Context)类

package com.yanyu.Strategyer;public class SalesMan {//持有抽象策略角色的引用private Strategy strategy;public SalesMan(Strategy strategy) {this.strategy = strategy;}public Strategy getStrategy() {return strategy;}public void setStrategy(Strategy strategy) {this.strategy = strategy;}//向客户展示促销活动public void salesManShow(){strategy.show();}
}

客户端类

package com.yanyu.Strategyer;public class Client {public static void main(String[] args) {//春节来了, 使用春节促销活动SalesMan salesMan = new SalesMan(new StrategyA());// 展示促销活动salesMan.salesManShow();System.out.println("=============");// 中秋节到了, 使用中秋节的促销活动salesMan.setStrategy (new StrategyB());// 展示促销活动salesMan.salesManShow();}
}

1.4优缺点

1,优点:

  • 策略类之间可以自由切换

    由于策略类都实现同一个接口,所以使它们之间可以自由切换。

  • 易于扩展

    增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“

  • 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。

2,缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
  • 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量

1.5使用场景

  • 当你想使用对象中各种不同的算法变体, 并希望能在运行时切换算法时, 可使用策略模式;

  • 当你有许多仅在执行某些行为时略有不同的相似类时, 可使用策略模式;

  • 如果算法在上下文的逻辑中不是特别重要, 使用该模式能将类的业务逻辑与其算法实现细节隔离开来;

  • 当类中使用了复杂条件运算符以在同一算法的不同变体中切换时, 可使用该模式。

  • 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。
  • 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为

二、 命令模式

2.1概述

日常生活中,我们出去吃饭都会遇到下面的场景。

命令模式是一种行为设计模式,将请求或操作封装成对象,从而使请求者和接收者松耦合,使发出请求的责任和执行请求的责任分割开。在命令模式中,命令就像是一个对象,可以被存储、重复、撤销、恢复等操作,因此它可以通过队列、日志等方式来管理和操作。

为什么需要命令模式

假如你正在开发一款新的文字编辑器, 当前的任务是创建一个包含多个按钮的工具栏, 并让每个按钮对应编辑器的不同操作。 你创建了一个非常简洁的 按钮类, 它不仅可用于生成工具栏上的按钮, 还可用于生成各种对话框的通用按钮。

最简单的解决方案是在使用按钮的每个地方都创建大量的子类。 这些子类中包含按钮点击后必须执行的代码。

zeren

你很快就意识到这种方式有严重缺陷。 首先, 你创建了大量的子类, 当每次修改基类 按钮时, 你都有可能需要修改所有子类的代码。 简单来说, GUI 代码以一种拙劣的方式依赖于业务逻辑中的不稳定代码。 还有一个部分最难办。 复制/粘贴文字等操作可能会在多个地方被调用。 例如用户可以点击工具栏上小小的 “复制” 按钮, 或者通过上下文菜单复制一些内容, 又或者直接使用键盘上的 Ctrl+C 。

最简单的解决方案是在使用按钮的每个地方都创建大量的子类。 这些子类中包含按钮点击后必须执行的代码。

zeren

你很快就意识到这种方式有严重缺陷。 首先, 你创建了大量的子类, 当每次修改基类 按钮时, 你都有可能需要修改所有子类的代码。 简单来说, GUI 代码以一种拙劣的方式依赖于业务逻辑中的不稳定代码。 还有一个部分最难办。 复制/粘贴文字等操作可能会在多个地方被调用。 例如用户可以点击工具栏上小小的 “复制” 按钮, 或者通过上下文菜单复制一些内容, 又或者直接使用键盘上的 Ctrl+C 。

用命令模式解决问题

软件设计通常会将关注点进行分离。 最常见的例子: 一层负责用户图像界面; 另一层负责业务逻辑。 GUI 层负责在屏幕上渲染美观的图形, 捕获所有输入并显示用户和程序工作的结果。 当需要完成一些重要内容时 (比如计算月球轨道或撰写年度报告), GUI 层则会将工作委派给业务逻辑底层。

这在代码中看上去就像这样: 一个 GUI 对象传递一些参数来调用一个业务逻辑对象。 这个过程通常被描述为一个对象发送请求给另一个对象。

 2.2结构

命令模式包含以下主要角色:

  • 抽象命令类(Command)角色: 定义命令的接口,声明执行的方法。
  • 具体命令(Concrete Command)角色:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
  • 实现者/接收者(Receiver)角色: 负责执行具体的命令操作。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
  • 调用者/请求者(Invoker)角色: 负责调用命令并执行。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。

2.3实现

将上面的案例用代码实现,那我们就需要分析命令模式的角色在该案例中由谁来充当。

服务员: 就是调用者角色,由她来发起命令。

资深大厨: 就是接收者角色,真正命令执行的对象。

订单: 命令中包含订单。

类图如下:

抽象命令类

package com.yanyu.Commander;public interface Command {void execute();//只需要定义一个统一的执行方法
}

具体命令(Concrete Command)角色

package com.yanyu.Commander;import java.util.Set;public class OrderCommand implements Command {//持有接受者对象private SeniorChef receiver; // 命令模式中的接收者对象private Order order; // 命令的参数public OrderCommand(SeniorChef receiver, Order order){this.receiver = receiver; // 初始化接收者对象this.order = order; // 初始化命令的参数}public void execute()  {System.out.println(order.getDiningTable() + "桌的订单:"); // 输出订单信息Set<String> keys = order.getFoodDic().keySet(); // 获取订单中食物的键集合for (String key : keys) {receiver.makeFood(order.getFoodDic().get(key),key); // 调用接收者对象的方法执行制作食物的操作}try {Thread.sleep(100); // 停顿一下 模拟做饭的过程} catch (InterruptedException e) {e.printStackTrace();}System.out.println(order.getDiningTable() + "桌的饭弄好了"); // 输出制作完成的信息}
}

接收者(Receiver)角色

package com.yanyu.Commander;// 资深大厨类 是命令的Receiver
public class SeniorChef {public void makeFood(int num,String foodName) {System.out.println(num + "份" + foodName);}
}

调用者

package com.yanyu.Commander;import java.util.ArrayList;public class Waitor {private ArrayList<Command> commands;//可以持有很多的命令对象public Waitor() {commands = new ArrayList();}public void setCommand(Command cmd){commands.add(cmd);}// 发出命令 喊 订单来了,厨师开始执行public void orderUp() {System.out.println("美女服务员:叮咚,大厨,新订单来了.......");for (int i = 0; i < commands.size(); i++) {Command cmd = commands.get(i);if (cmd != null) {cmd.execute();}}}
}

命令的请求

package com.yanyu.Commander;import java.util.HashMap;
import java.util.Map;public class Order {// 餐桌号码private int diningTable;// 用来存储餐名并记录份数private Map<String, Integer> foodDic = new HashMap<String, Integer>();public int getDiningTable() {return diningTable; // 获取餐桌号码}public void setDiningTable(int diningTable) {this.diningTable = diningTable; // 设置餐桌号码}public Map<String, Integer> getFoodDic() {return foodDic; // 获取食物名称和数量的映射}public void setFoodDic(String name, int num) {foodDic.put(name,num); // 添加食物名称和数量的映射}
}

客户端类

package com.yanyu.Commander;public class Client {public static void main(String[] args) {//创建2个orderOrder order1 = new Order();order1.setDiningTable(1);order1.getFoodDic().put("西红柿鸡蛋面",1);order1.getFoodDic().put("小杯可乐",2);Order order2 = new Order();order2.setDiningTable(3);order2.getFoodDic().put("尖椒肉丝盖饭",1);order2.getFoodDic().put("小杯雪碧",1);//创建接收者SeniorChef receiver=new SeniorChef();//将订单和接收者封装成命令对象OrderCommand cmd1 = new OrderCommand(receiver, order1);OrderCommand cmd2 = new OrderCommand(receiver, order2);//创建调用者 waitorWaitor invoker = new Waitor();invoker.setCommand(cmd1);invoker.setCommand(cmd2);//将订单带到柜台 并向厨师喊 订单来了invoker.orderUp();}
}

2.4 优缺点

1,优点:

  • 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
  • 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
  • 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
  • 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。

2,缺点:

  • 使用命令模式可能会导致某些系统有过多的具体命令类。
  • 系统结构更加复杂。

2.5使用场景

  • 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
  • 系统需要在不同的时间指定请求、将请求排队和执行请求。
  • 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。

2.6源码分析

在JDK中,命令模式的经典实现是Runnable接口和java.util.concurrent包中的Executor框架。Runnable接口定义了一个执行动作的协议,而Executor框架则提供了一些实现Runnable接口的类(如ThreadPoolExecutor),以及执行Runnable对象的方法。

以下是一个简单的示例,我们将使用Runnable接口和Executor框架来实现命令模式:

public class CommandPatternJDKExample {public static void main(String[] args) {// 创建一个命令对象Runnable command = new ConcreteCommand();// 创建一个执行器对象Executor executor = Executors.newSingleThreadExecutor();// 执行命令executor.execute(command);}
}// 具体命令类
class ConcreteCommand implements Runnable {@Overridepublic void run() {System.out.println("命令被执行了");}
}

在上面的示例中,我们创建了一个ConcreteCommand类,它实现了Runnable接口,并且在run()方法中执行了一个简单的命令。然后,我们使用Executors类创建了一个执行器对象,并调用了它的execute()方法来执行这个命令。

三、策略模式实验

任务描述

在多个裁判负责打分的单人跳水比赛中,每位裁判给选手一个得分,选手的最后得分是根据全体裁判的得分计算出来的。现有5名裁判和7人裁判两种评分计算方案,以后可能会有更多计算方案。

  • 5名裁判员评分规则:5名裁判员打出分数以后,先删去最高和最低的无效分,余下3名裁判员的分数之和乘以运动员所跳动作的难度系数,便得出该动作的实得分;
  • 7名裁判员评分规则:方法与5名裁判员评分方法相同,但7人裁判员算出的得分最后还应除以5,再乘以3。

本关任务:请设计一种能兼容多种评分策略的架构,且用户可以自主选择其中一种策略作为比赛的评分方案。

实现方式

  1. 从上下文类中找出修改频率较高的算法 (也可能是用于在运行时选择某个算法变体的复杂条件运算符);

  2. 声明该算法所有变体的通用策略接口;

  3. 将算法逐一抽取到各自的类中, 它们都必须实现策略接口;

  4. 在上下文类中添加一个成员变量用于保存对于策略对象的引用。 然后提供设置器以修改该成员变量。 上下文仅可通过策略接口同策略对象进行交互, 如有需要还可定义一个接口来让策略访问其数据;

  5. 客户端必须将上下文类与相应策略进行关联, 使上下文可以预期的方式完成其主要工作。

编程要求

根据提示,在右侧编辑器 Begin-End 内补充代码:

  • PlayerScore:上下文环境类;
  • Codepoints:抽象策略;
  • Codepoints5:5人裁判评分策略类;
  • Codepoints7:7人裁判评分策略类;
  • Client:客户端类。

测试说明

平台会对你编写的代码进行测试,第一行给出一个正整数 n(表示裁判人数)和一个实数 k(表示跳水难度系数)。第二行给出 n 个实数(评分成绩),中间以空格进行分隔。输出最后结果,格式为 The final score is XX.XX,保留小数点后两位。

测试输入: 5 2.0 5 5.5 5 5 4.5 预期输出: The final score is 30.00

测试输入: 7 2.0 5 5.5 5 5 4.5 5 5 预期输出: The final score is 30.00

抽象策略(Strategy)类

package step1;/********** Begin *********/
public interface Codepoints{double computerScore(double []a,double difficulty);}
/********** End *********/

 具体策略(Concrete Strategy)类

package step1;/********** Begin *********/
import java.util.Arrays;public class Codepoints5 implements Codepoints{public double computerScore(double[]a,double difficulty){if(a.length<=2)return 0;double score,sum=0;Arrays.sort(a);//排序数组for (int i=1;i<a.length-1;i++){sum=sum+a[i];}score=sum*difficulty;return score;}
}/********** End *********/
package step1;/********** Begin *********/
import java.util.Arrays;public class Codepoints7 implements Codepoints{public double computerScore(double[]a,double difficulty){if(a.length<=2)return 0;double score,sum=0;Arrays.sort(a);//排序数组for (int i=1;i<a.length-1;i++){sum=sum+a[i];}score=sum/5.0*3*difficulty;return score;}
}/********** End *********/

环境(Context)类

package step1;/********** Begin *********/public class PlayerScore{private Codepoints codepoints;public void setStrategy(Codepoints codepoints){this.codepoints=codepoints;}public double Calculate(double []a,double difficulty){return codepoints.computerScore(a,difficulty);}
}
/********** End *********/

客户端类


package step1;import java.util.Scanner;public class Client {public static void main(String[] args) {/********** Begin *********/PlayerScore player=new PlayerScore ();Scanner scanner = new Scanner(System.in);int n =scanner.nextInt();// 裁判人数double diff=scanner.nextDouble();//动作的难度系数double[] array=new double [n];// 裁判的评分for (int i=0 ; i<n ; i++){array[i] = scanner.nextDouble();}if (n==5){player.setStrategy(new Codepoints5());}else if (n==7) {player.setStrategy(new Codepoints7());}System.out.println("The final score is "+ String.format("%.2f", player.Calculate(array,diff)));/********** End *********/}
}

四、命令模式实验

任务描述

zeren

在植物大战僵尸的游戏设计中,植物战士是兵营生产的,玩家通过点击界面上“图片按钮”向兵营发出生产命令,兵营接受命令后每生产一个植物战士需要冷却一定的时间才能继续生产。

本关任务:本模拟程序中只需要实现一种植物战士的生产,请你用命令模式实现。

实现方式

  1. 声明仅有一个执行方法的命令接口;

  2. 抽取请求并使之成为实现命令接口的具体命令类。 每个类都必须有一组成员变量来保存请求参数和对于实际接收者对象的引用。 所有这些变量的数值都必须通过命令构造函数进行初始化;

  3. 找到担任发送者职责的类。 在这些类中添加保存命令的成员变量。 发送者只能通过命令接口与其命令进行交互。 发送者自身通常并不创建命令对象, 而是通过客户端代码获取;

  4. 修改发送者使其执行命令, 而非直接将请求发送给接收者;

  5. 客户端必须按照以下顺序来初始化对象:

    •  创建接收者;
    •  创建命令, 如有需要可将其关联至接收者;
    •  创建发送者并将其与特定命令关联。

编程要求

根据提示,在右侧编辑器 Begin-End 内补充 “CampInvokers.java”和 “ProduceCommand.java” 文件代码,其它地方不要修改。

测试说明

平台会对你编写的代码进行测试,请输入发出生产命令的个数和兵营冷却时间(毫秒)。 输入结束后,为了模拟界面操作,系统会在 1000 毫秒内持续监控兵营接到的命令。 测试输入:6 200 预期输出: 豌豆射手生产出来了 豌豆射手生产出来了 豌豆射手生产出来了 豌豆射手生产出来了 豌豆射手生产出来了

测试输入:6 500 预期输出: 豌豆射手生产出来了 豌豆射手生产出来了

抽象命令类

package step1;public abstract class Commands{public abstract void Execute();
}

具体命令

package step1;public class ProduceCommand extends Commands{@Overridepublic void Execute() {/********** Begin *********///生产植物战士new Peashooter();/********** End *********/}
}
package step1;
//所有战士的基类
public interface IBotany {
}
package step1;
//植物战士
public class Peashooter implements IBotany {public Peashooter(){System.out.println("豌豆射手生产出来了");}
}

接收者(Receiver)角色

调用者

package step1;import java.util.ArrayList;
import java.util.List;// 兵营就是命令的管理者
public class CampInvokers {private final List<Commands> commands = new ArrayList<>(); // 命令队列private final long TrainTimer; // 训练冷却时间private long timer; // 当前时间// 构造函数,初始化训练冷却时间和当前时间public CampInvokers(long trainTime){TrainTimer=trainTime;timer=0;}// 添加训练命令到命令队列public void Train(){// 将生产命令加入到命令队列commands.add(new ProduceCommand());}// 执行命令队列中的命令public void ExecuteCommand(){if (commands.size() <= 0) return;if (timer+TrainTimer <= System.currentTimeMillis()){// 执行队列里最上面的命令commands.get(0).Execute(); // 移除最上面的命令commands.remove(0); // 重置冷却时间timer = System.currentTimeMillis(); }}// 取消训练命令public void CancelTrainCommand(){if (commands.size() > 0){commands.remove(commands.size() - 1);if (commands.size() == 0){timer = System.currentTimeMillis();}}}
}

客户端类 

package step1;import java.util.Scanner;// 客户端类,用于演示命令模式
public class Client {public static void main(String[] args){Scanner scanner = new Scanner(System.in);// 从用户输入获取训练次数和训练冷却时间int number = scanner.nextInt();long traintime = scanner.nextLong();long currtime= System.currentTimeMillis();// 创建兵营管理者对象CampInvokers camp = new CampInvokers(traintime);// 循环训练指定次数for (int i = 0; i < number; i++) {camp.Train();}// 循环执行命令直至时间到达1秒后while (true){camp.ExecuteCommand();if(currtime+1000<System.currentTimeMillis())break;}}
}

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

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

相关文章

看Spring源码不得不会的@Enable模块驱动实现原理讲解

这篇文章我想和你聊一聊 spring的Enable模块驱动的实现原理。 在我们平时使用spring的过程中&#xff0c;如果想要加个定时任务的功能&#xff0c;那么就需要加注解EnableScheduling&#xff0c;如果想使用异步的功能&#xff0c;那就要加EnableScheduling注解&#xff0c;其实…

「盘点」界面控件DevExtreme UI v23.1中的API增强

DevExtreme拥有高性能的HTML5 / JavaScript小部件集合&#xff0c;使您可以利用现代Web开发堆栈&#xff08;包括React&#xff0c;Angular&#xff0c;ASP.NET Core&#xff0c;jQuery&#xff0c;Knockout等&#xff09;构建交互式的Web应用程序。从Angular和Reac&#xff0c…

【赠书第10期】从概念到现实:ChatGPT和Midjourney的设计之旅

文章目录 前言 1 ChatGPT的崛起 2 Midjourney的探索 3 技术创新的交汇 4 对未来的影响 5 结论 6 推荐图书 7 粉丝福利 前言 在过去的几年里&#xff0c;自然语言处理和聊天模型的领域取得了飞速的发展。ChatGPT 作为一个由OpenAI 开发的大型语言模型&#xff0c;以其强…

【opencv】计算机视觉基础知识

目录 前言 1、什么是计算机视觉 2、图片处理基础操作 2.1 图片处理&#xff1a;读入图像 2.2 图片处理&#xff1a;显示图像 2.3 图片处理&#xff1a;图像保存 3、图像处理入门基础 3.1 图像成像原理介绍 3.2 图像分类 3.2.1 二值图像 3.2.2灰度图像 3.2.3彩色图像…

算法与数据结构有区别吗?

算法和数据结构并不是同一件事。严格来说&#xff0c;它们并不是等效的。但是&#xff0c;我们通常在使用的时候会互换这两个术语。为了简便&#xff0c;后文我们会用数据结构这个术语来指代“数据结构及其所有相关的方法”。 有很多方法可以用来说明这两个术语之间的区别&…

企业软件手机app定制开发趋势|小程序网站搭建

企业软件手机app定制开发趋势|小程序网站搭建 随着移动互联网的快速发展和企业数字化转型的加速&#xff0c;企业软件手机App定制开发正成为一个新的趋势。这种趋势主要是由于企业对于手机App的需求增长以及现有的通用应用不能满足企业特定需求的情况下而产生的。 1.企业软件手…

​iOS Class Guard github用法、工作原理和安装详解及使用经验总结

iOS Class Guard是一个用于OC类、协议、属性和方法名混淆的命令行工具。它是class-dump的扩展。这个工具会生成一个symbol table&#xff0c;这个table在编译期间会包含进工程中。iOS-Class-Guard能有效的隐藏绝大多数的类、协议、方法、属性和 实例变量 名。 iOS-Class-Guard不…

在 S/4HANA、ECC 和 ERP 上轻松扩展或简化 SAP WM,并将其自动化到移动环境中

为您的 SAP WM 提供完整的本地 SAP 图形用户界面 基于原生通道架构&#xff08;NCA&#xff09;&#xff0c;iOS、Android 和手持 Scanguns 版 Liquid UI 可与 SAP WM 原生连接&#xff0c;同时保留 SAP GUI 丰富的事务处理功能。它使您无需编程即可直接从移动设备访问 MIGO、…

安全意识成熟度模型

安全意识成熟度模型是指导企业组织有效识别、管理和衡量团队和员工的安全意识风险&#xff0c;评估和衡量团队和员工的安全意识的评估模型。这套模型是多年以来通过对200多个具有安全意识的职员进行调研后建立的&#xff0c;安全意识成熟度模型使组织能够确定当前安全意识的成熟…

深度学习——激活函数汇总

深度学习——激活函数汇总 一、ReLU 一、ReLU 参考资料&#xff1a; https://zhuanlan.zhihu.com/p/428448728

C++核心编程——运算符重载

C核心编程——运算符重载 运算符重载的方法运算符重载函数作成员函数与友元函数重载双目运算符重载单目运算符重载流插入运算符和"<<"和流提取运算符">>"重载流插入运算符和"<<"流提取运算符">>" 运算符重载的…

LabVIEW开发自适应降噪ANC

LabVIEW开发自适应降噪ANC 在许多情况下&#xff0c;信号很嘈杂&#xff0c;必须消除噪声。自适应降噪&#xff08;ANC&#xff09;是可用于消除信号噪声的主要实时方法之一。可以使用LabVIEW自适应滤滤器工具包来设计ANC应用程序。本文介绍使用自适应筛选器工具包的ANC的一些…

【深度学习】概率图模型(二)有向图模型详解(条件独立性、局部马尔可夫性及其证明)

文章目录 一、有向图模型1. 贝叶斯网络的定义2. 条件独立性及其证明a. 间接因果关系 X 3 → X 2 → X 1 X_3 \rightarrow X_2 \rightarrow X_1 X3​→X2​→X1​b. 间接果因关系 X 1 → X 2 → X 3 X_1 \rightarrow X_2 \rightarrow X_3 X1​→X2​→X3​c. 共因关系 X 1 ← X…

android上架之获取平台公钥、签名 MD5 值

app上架需要用到的两个参数公钥、签名 MD5 步骤 1. 下载jadx-gui 工具&#xff0c;下载 2. 下载成后&#xff0c;解压压缩包&#xff0c;双击 jadx-gui-1.4.7.exe 运行。 3. 运行后&#xff0c;在页面左上方单击文件 > 打开文件&#xff0c;打开 APK 包 4. 打开 APK 包后…

Jvm常见问题

1. 为什么用元空间替换永久代 避免OOM异常&#xff1a;永久代中存放了很多JVM需要的类信息&#xff0c;这些数据大多数是不会被清理的&#xff0c;所以Full GC往往无法回收多少空间。而永久代的空间是有限的&#xff0c;如果经常加载新的类进来或者频繁的创建和删除类&#xf…

前端页面转pdf

首先&#xff0c;需要安装两个库 html2canvasjspdf 先引入这个公用的html转pdf的方法 /**path:src/utils/htmlToPdf.jsname:导出页面为pdf格式 **/ import html2Canvas from "html2canvas1.4.1"; import JsPDF from "jspdf2.5.1";const htmlToPdf {get…

2.Ansible的copy模块,我最常用的模块

1. 简述 先从我自身的情况来说&#xff0c;我不是运维人员&#xff0c;并且对linux操作也不是特别熟悉&#xff0c;所以工作中我使用ansible基本就是在平常的自动化部署中&#xff0c;而使用最多的模块就是copy模块。我使用copy模块也主要是来替换生产环境的配置文件。所以&am…

rabbitMQ镜像队列的使用

在rabbitMQ集群中&#xff0c;默认发送消息时&#xff0c;队列默认时在一个节点上存在的。 我们以node01 node02 node03三节点集群为例&#xff0c;在node01声明队列发送消息后&#xff0c;发现&#xff1a; 测试队列只在节点node01上出现。 我们手动停止node01后&#xff0c…

Tomcat外传

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 本篇开始&#xff0c;我…

C++11线程以及线程同步

C11中提供的线程类std::thread,基于此类创建一个新的线程相对简单&#xff0c;只需要提供线程函数和线程对象即可 一.命名空间 this_thread C11 添加一个关于线程的命名空间std::this_pthread ,此命名空间中提供四个公共的成员函数&#xff1b; 1.1 get_id() 调用命名空间s…