【设计模式——学习笔记】23种设计模式——命令模式Command(原理讲解+应用场景介绍+案例介绍+Java代码实现)

案例引入

  • 有一套智能家电,其中有照明灯、风扇、冰箱、洗衣机,这些智能家电来自不同的厂家,我们不想针对每一种家电都安装一个手机App来分别控制,希望只要一个app就可以控制全部智能家电
  • 要实现一个app控制所有智能家电的需要,则每个智能家电厂家都要提供一个统一的接口给app调用,这样可以考虑使用命令模式
  • 命令模式可将“动作的请求者”从“动作的执行者”对象中解耦出来
  • 在我们的例子中,动作的请求者是手机app,动作的执行者是每个厂商的一个家电产品

介绍

基础介绍

  • 一个类在进行工作时会调用自己或是其他类的方法,虽然调用结果会反映在对象的状态中,但并不会留下工作的历史记录。这时,如果有一个类用来表示“请示进行这项工作”的“命令”就会方便很多。每一项想做的工作就不再是“方法的调用”这种动态处理了,而是一个表示命令的类的实例,即可以用“物”来表示。要想管理工作的历史记录,只需管理这些实例的集合即可,而且还可以随时再次执行过去的命令,或是将多个过去的命令整合为一个新命令并执行。这样的模式称为命令模式
  • 命令模式使得请求发送者请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活,实现解耦,我们只需在程序运行时指定具体的请求接收者即可
  • 在命令模式中,会将一个请求封装为一个对象,以便使用不同参数来表示不同的请求(即命令),同时命令模式也支持可撤销的操作
  • 通俗易懂的理解:将军发布命令,士兵去执行(将军只需要发布一个进攻命令即可,不需要指定哪位士兵要做什么,士兵就会各司其职)。其中有几个角色:将军(命令发布者)、士兵(命令的具体执行者)、命令(连接将军和士兵)

登场角色

  • Command(命令):负责定义命令的接口(API)
  • ConcreteCommand(具体的命令):ConcreteCommand角色负责实现在Command角色中定义的接口(API)。聚合接收者,将一个接收者对象与一个动作绑定,调用接收者相应的操作来实现execute
  • Receiver(接收者):Receiver角色是执行命令的对象,知道如何实施和执行一个请求对应的操作
  • Client(请求者):Client角色负责生成ConcreteCommand角色并分配Receiver角色
  • Invoker(发动者):调用在Command 角色中定义的接口(API)

在这里插入图片描述

案例实现

案例一

在这里插入图片描述

实现

【Commond】

package com.atguigu.command;/*** 创建命令接口*/
public interface Command {/*** 执行动作(操作)*/public void execute();/*** 撤销动作(操作)*/public void undo();
}

【电灯命令执行者】

package com.atguigu.command;/*** 真正执行者*/
public class LightReceiver {public void on() {System.out.println(" 电灯打开了.. ");}public void off() {System.out.println(" 电灯关闭了.. ");}
}

【关灯命令】

package com.atguigu.command;public class LightOffCommand implements Command {/*** 聚合LightReceiver*/LightReceiver light;/*** 构造器* @param light*/public LightOffCommand(LightReceiver light) {super();this.light = light;}@Overridepublic void execute() {// 调用接收者的方法light.off();}@Overridepublic void undo() {// 调用接收者的方法light.on();}
}

【开灯命令】

package com.atguigu.command;public class LightOnCommand implements Command {/*** 聚合LightReceiver*/LightReceiver light;/*** 构造器** @param light*/public LightOnCommand(LightReceiver light) {super();this.light = light;}@Overridepublic void execute() {//调用接收者的方法light.on();}@Overridepublic void undo() {//调用接收者的方法light.off();}}

【电视命令执行者】

package com.atguigu.command;public class TVReceiver {public void on() {System.out.println(" 电视机打开了.. ");}public void off() {System.out.println(" 电视机关闭了.. ");}
}

【关电视命令】

package com.atguigu.command;public class TVOffCommand implements Command {/*** 聚合TVReceiver*/TVReceiver tv;/*** 构造器** @param tv*/public TVOffCommand(TVReceiver tv) {super();this.tv = tv;}@Overridepublic void execute() {// 调用接收者的方法tv.off();}@Overridepublic void undo() {// 调用接收者的方法tv.on();}
}

【开电视命令】

package com.atguigu.command;public class TVOnCommand implements Command {/*** 聚合TVReceiver*/TVReceiver tv;/*** 构造器** @param tv*/public TVOnCommand(TVReceiver tv) {super();this.tv = tv;}@Overridepublic void execute() {// 调用接收者的方法tv.on();}@Overridepublic void undo() {// 调用接收者的方法tv.off();}
}

【空命令】

package com.atguigu.command;/*** 没有任何命令,即空执行: 用于初始化每个按钮, 当调用空命令时,对象什么都不做* 其实,这样是一种设计模式, 可以省掉对空判断* @author Administrator**/
public class NoCommand implements Command {@Overridepublic void execute() {}@Overridepublic void undo() {}} 

【遥控器】

package com.atguigu.command;public class RemoteController {/*** 开 按钮的命令数组*/Command[] onCommands;Command[] offCommands;/*** 执行撤销的命令,必须要记住上一次执行的命令对应的撤销命令才能撤销*/Command undoCommand;/*** 构造器,完成对按钮初始化*/public RemoteController() {onCommands = new Command[5];offCommands = new Command[5];// 初始化五组命令,初始化为空命令for (int i = 0; i < 5; i++) {onCommands[i] = new NoCommand();offCommands[i] = new NoCommand();}}/*** 给我们的按钮设置你需要的命令** @param no 命令编号* @param onCommand* @param offCommand*/public void setCommand(int no, Command onCommand, Command offCommand) {onCommands[no] = onCommand;offCommands[no] = offCommand;}/*** 按下开按钮** @param no*/public void onButtonWasPushed(int no) {// 找到你按下的开的按钮, 并调用对应方法onCommands[no].execute();// 记录这次的操作,用于撤销undoCommand = onCommands[no];}/*** 按下开按钮** @param no*/public void offButtonWasPushed(int no) {// 找到你按下的关的按钮, 并调用对应方法offCommands[no].execute();// 记录这次的操作,用于撤销undoCommand = offCommands[no];}/*** 按下撤销按钮*/public void undoButtonWasPushed() {undoCommand.undo();}}

【客户端】

package com.atguigu.command;public class Client {public static void main(String[] args) {//使用命令设计模式,完成通过遥控器,对电灯的操作//创建电灯的对象(接受者)LightReceiver lightReceiver = new LightReceiver();//创建电灯相关的开关命令LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);//需要一个遥控器RemoteController remoteController = new RemoteController();//给我们的遥控器设置命令, 比如 no = 0 是电灯的开和关的操作remoteController.setCommand(0, lightOnCommand, lightOffCommand);System.out.println("--------按下灯的开按钮-----------");remoteController.onButtonWasPushed(0);System.out.println("--------按下灯的关按钮-----------");remoteController.offButtonWasPushed(0);System.out.println("--------按下撤销按钮-----------");remoteController.undoButtonWasPushed();System.out.println("=========使用遥控器操作电视机==========");TVReceiver tvReceiver = new TVReceiver();TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver);TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver);//给我们的遥控器设置命令, 比如 no = 1 是电视机的开和关的操作remoteController.setCommand(1, tvOnCommand, tvOffCommand);System.out.println("--------按下电视机的开按钮-----------");remoteController.onButtonWasPushed(1);System.out.println("--------按下电视机的关按钮-----------");remoteController.offButtonWasPushed(1);System.out.println("--------按下撤销按钮-----------");remoteController.undoButtonWasPushed();}}

【运行】

--------按下灯的开按钮-----------电灯打开了.. 
--------按下灯的关按钮-----------电灯关闭了.. 
--------按下撤销按钮-----------电灯打开了.. 
=========使用遥控器操作电视机==========
--------按下电视机的开按钮-----------电视机打开了.. 
--------按下电视机的关按钮-----------电视机关闭了.. 
--------按下撤销按钮-----------电视机打开了.. Process finished with exit code 0

案例二

介绍

这段示例程序是一个画图软件,它的功能很简单,即用户拖动鼠标时程序会绘制出红色圆点,点击 clear 按钮后会清除所有的圆点。

在这里插入图片描述

实现

在这里插入图片描述

【命令接口】

package com.atguigu.command.Sample.command;public interface Command {/*** 执行*/public abstract void execute();
}

【历史命令集:由多条命令整合成的命令】

如果保存这个实例,就可以永久保存历史数据

package com.atguigu.command.Sample.command;import java.util.Iterator;
import java.util.Stack;/*** 由多条命令整合成的命令*/
public class MacroCommand implements Command {/*** 存储命令的栈*/private Stack commands = new Stack();/*** 执行*/public void execute() {// 一次性执行一系列命令Iterator it = commands.iterator();while (it.hasNext()) {((Command) it.next()).execute();}}/*** 添加命令** @param cmd*/public void append(Command cmd) {if (cmd != this) {// 判断不是自己再添加进去,不然会死循环commands.push(cmd);}}/*** 删除最后一条命令*/public void undo() {if (!commands.empty()) {// 取出最后添加到栈的命令commands.pop();}}/*** 删除所有命令*/public void clear() {commands.clear();}
}

【绘制点命令】

package com.atguigu.command.Sample.drawer;import com.atguigu.command.Sample.command.Command;
import java.awt.*;public class DrawCommand implements Command {/*** 绘制对象*/protected Drawable drawable;/*** 绘制位置 Point 是 java.awt 包的类,含有 (x,y) 坐标*/private Point position;/*** 构造函数** @param drawable* @param position*/public DrawCommand(Drawable drawable, Point position) {this.drawable = drawable;this.position = position;}/*** 执行*/public void execute() {drawable.draw(position.x, position.y);}
}

【绘制对象接口】

package com.atguigu.command.Sample.drawer;public interface Drawable {public abstract void draw(int x, int y);
}

【绘图类】

package com.atguigu.command.Sample.drawer;import com.atguigu.command.Sample.command.MacroCommand;import java.awt.*;/*** 继承Canvas*/
public class DrawCanvas extends Canvas implements Drawable {/*** 颜色*/private Color color = Color.red;/*** 要绘制的圆点的半径*/private int radius = 6;/*** 命令的历史记录*/private MacroCommand history;/*** 构造函数** @param width* @param height* @param history*/public DrawCanvas(int width, int height, MacroCommand history) {// 设置画布尺寸setSize(width, height);// 设置画布颜色setBackground(Color.white);this.history = history;}/*** 重新全部绘制* @param g   the specified Graphics context*/public void paint(Graphics g) {history.execute();}/*** 绘制* @param x* @param y*/public void draw(int x, int y) {Graphics g = getGraphics();// 设置笔画颜色g.setColor(color);// 绘制圆点g.fillOval(x - radius, y - radius, radius * 2, radius * 2);}
}

【主类】

package com.atguigu.command.Sample;import com.atguigu.command.Sample.command.*;
import com.atguigu.command.Sample.drawer.*;import javax.swing.*;
import java.awt.event.*;public class Main extends JFrame implements ActionListener, MouseMotionListener, WindowListener {/*** 存储绘制的历史记录*/private MacroCommand history = new MacroCommand();/*** 绘制区域*/private DrawCanvas canvas = new DrawCanvas(400, 400, history);/*** 创建删除按钮*/private JButton clearButton  = new JButton("clear");/*** 构造函数* @param title*/public Main(String title) {super(title);this.addWindowListener(this);// 添加鼠标移动事件canvas.addMouseMotionListener(this);// 添加鼠标点击事件clearButton.addActionListener(this);/// 创建布局// 创建横向的盒子来存放按钮Box buttonBox = new Box(BoxLayout.X_AXIS);buttonBox.add(clearButton);// 创建纵向的盒子来存放按钮盒子和画布Box mainBox = new Box(BoxLayout.Y_AXIS);mainBox.add(buttonBox);mainBox.add(canvas);getContentPane().add(mainBox);pack();show();}/*** ActionListener接口中的方法* @param e*/public void actionPerformed(ActionEvent e) {if (e.getSource() == clearButton) {// 清空历史命令history.clear();// 清空画布canvas.repaint();}}public void mouseMoved(MouseEvent e) {}/***  MouseMotionListener接口中的方法* @param e*/public void mouseDragged(MouseEvent e) {// 鼠标位置一改变,就创建绘制点命令放到命令集合中Command cmd = new DrawCommand(canvas, e.getPoint());// 执行绘制cmd.execute();history.append(cmd);}/***  WindowListener接口中的方法* @param e*/public void windowClosing(WindowEvent e) {System.exit(0);}public void windowActivated(WindowEvent e) {}public void windowClosed(WindowEvent e) {}public void windowDeactivated(WindowEvent e) {}public void windowDeiconified(WindowEvent e) {}public void windowIconified(WindowEvent e) {}public void windowOpened(WindowEvent e) {}public static void main(String[] args) {new Main("Command Pattern Sample");}
}

在这里插入图片描述

【运行】

在这里插入图片描述

拓展

如何示例程序中增加“设置颜色”的功能。

【颜色命令】

package com.atguigu.command.A1.drawer;import com.atguigu.command.A1.command.Command;import java.awt.*;public class ColorCommand implements Command {/*** 绘制对象*/protected Drawable drawable;/*** 颜色*/private Color color;/*** 构造函数** @param drawable* @param color*/public ColorCommand(Drawable drawable, Color color) {this.drawable = drawable;this.color = color;}/*** 执行* 设置画笔的颜色*/public void execute() {drawable.setColor(color);}
}

【主类】

package com.atguigu.command.A1;import com.atguigu.command.A1.command.Command;
import com.atguigu.command.A1.command.MacroCommand;
import com.atguigu.command.A1.drawer.ColorCommand;
import com.atguigu.command.A1.drawer.DrawCanvas;
import com.atguigu.command.A1.drawer.DrawCommand;import javax.swing.*;
import java.awt.*;
import java.awt.event.*;public class Main extends JFrame implements ActionListener, MouseMotionListener, WindowListener {private MacroCommand history = new MacroCommand();private DrawCanvas canvas = new DrawCanvas(400, 400, history);private JButton clearButton = new JButton("clear");/*** 红色按钮*/private JButton redButton = new JButton("red");/*** 绿色按钮*/private JButton greenButton = new JButton("green");/*** 蓝色按钮*/private JButton blueButton = new JButton("blue");/*** 构造函数** @param title*/public Main(String title) {super(title);this.addWindowListener(this);canvas.addMouseMotionListener(this);clearButton.addActionListener(this);redButton.addActionListener(this);greenButton.addActionListener(this);blueButton.addActionListener(this);Box buttonBox = new Box(BoxLayout.X_AXIS);buttonBox.add(clearButton);buttonBox.add(redButton);buttonBox.add(greenButton);buttonBox.add(blueButton);Box mainBox = new Box(BoxLayout.Y_AXIS);mainBox.add(buttonBox);mainBox.add(canvas);getContentPane().add(mainBox);pack();show();}/*** ActionListener接口中的方法* 点击不同颜色的按钮,设置不同颜色画笔** @param e*/public void actionPerformed(ActionEvent e) {if (e.getSource() == clearButton) {history.clear();canvas.init();canvas.repaint();} else if (e.getSource() == redButton) {Command cmd = new ColorCommand(canvas, Color.red);history.append(cmd);cmd.execute();} else if (e.getSource() == greenButton) {Command cmd = new ColorCommand(canvas, Color.green);history.append(cmd);cmd.execute();} else if (e.getSource() == blueButton) {Command cmd = new ColorCommand(canvas, Color.blue);history.append(cmd);cmd.execute();}}/*** MouseMotionListener接口中的方法** @param e*/public void mouseMoved(MouseEvent e) {}public void mouseDragged(MouseEvent e) {Command cmd = new DrawCommand(canvas, e.getPoint());history.append(cmd);cmd.execute();}/*** WindowListener接口中的方法** @param e*/public void windowClosing(WindowEvent e) {System.exit(0);}public void windowActivated(WindowEvent e) {}public void windowClosed(WindowEvent e) {}public void windowDeactivated(WindowEvent e) {}public void windowDeiconified(WindowEvent e) {}public void windowIconified(WindowEvent e) {}public void windowOpened(WindowEvent e) {}public static void main(String[] args) {new Main("Command Pattern Sample");}
}

【运行】

在这里插入图片描述

命令模式在JdbcTemplate源码中的应用

应用模式和标准的命令模式有点区别,但是精髓是差不多的

在这里插入图片描述

在这里插入图片描述

还有其他的命令执行者

在这里插入图片描述

在这里插入图片描述

总结

【优点】

  • 发起请求的对象执行请求的对象解耦。发起请求的对象是调用者,调用者只要调用命令对象的execute()方法就可以让接收者工作,而不必知道具体的接收者对象是谁、是如何实现的。命令对象(就是具体的命令)会负责让接收者执行调用者请求的动作,也就是说:”请求发起者”和“请求执行者”之间的解耦是通过命令对象实现的,命令对象起到了纽带桥梁的作用
  • 命令模式容易设计一个命令队列。只要把命令对象放到队列,就可以多线程地执行命令。不仅如此,还容易将命令执行的历史纪录保存起来
  • 命令模式容易实现对请求的撤销和重做
  • 空命令也是一种设计模式,它为我们省去了判空的操作。在上面的实例中,如果没有用空命令,我们每按下一个按键都要判空,这给我们编码带来一定的麻烦(声明命令数组时,首先将数组的元素全部初始化为空命令)

【缺点】

  • 可能导致某些系统有过多的具体命令类,增加了系统的复杂度

文章说明

  • 本文章为本人学习尚硅谷的学习笔记,文章中大部分内容来源于尚硅谷视频(点击学习尚硅谷相关课程),也有部分内容来自于自己的思考,发布文章是想帮助其他学习的人更方便地整理自己的笔记或者直接通过文章学习相关知识,如有侵权请联系删除,最后对尚硅谷的优质课程表示感谢。
  • 本人还同步阅读《图解设计模式》书籍(图解设计模式/(日)结城浩著;杨文轩译–北京:人民邮电出版社,2017.1),进而综合两者的内容,让知识点更加全面

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

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

相关文章

Jenkins 自动化部署实例讲解,另附安装教程!

【2023】Jenkins入门与安装_jenkins最新版本_丶重明的博客-CSDN博客 也可以结合这个互补看 前言 你平常在做自己的项目时&#xff0c;是否有过部署项目太麻烦的想法&#xff1f;如果你是单体项目&#xff0c;可能没什么感触&#xff0c;但如果你是微服务项目&#xff0c;相…

JVM的组件、自动垃圾回收的工作原理、分代垃圾回收过程、可用的垃圾回收器类型

详细画的图片 https://www.processon.com/diagraming/64c8aa11c07d99075d934311 官方网址 https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html 相关概念 年轻代是所有新对象被分配和老化的地方。当年轻代填满时&#xff0c;这会导致minor …

Rust dyn - 动态分发 trait 对象

dyn - 动态分发 trait 对象 dyn是关键字&#xff0c;用于指示一个类型是动态分发&#xff08;dynamic dispatch&#xff09;&#xff0c;也就是说&#xff0c;它是通过trait object实现的。这意味着这个类型在编译期间不确定&#xff0c;只有在运行时才能确定。 practice tr…

《Spring Boot源码解读与原理分析》书籍推荐

Spring Boot 1.0.0 早在2014年就已经发布&#xff0c;只不过到了提倡“降本增效”的今天&#xff0c;Spring Boot才引起了越来越多企业的关注。Spring Boot是目前Java EE开发中颇受欢迎的框架之一。依托于底层Spring Framework的基础支撑&#xff0c;以及完善强大的特性设计&am…

设计模式之中介者模式

中介者模式 用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显示地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变他们之间的交互。 电脑主板的功能就类似于一个中介者 经典中介者模式UML 例子 经典的中介者模式 package com.tao.Ya…

Excel快捷键F1-F9详解:掌握实用快捷操作,提升工作效率

Excel是广泛应用于办公场景的优质电子表格软件&#xff0c;然而&#xff0c;许多人只是使用鼠标点击菜单和工具栏来完成操作&#xff0c;而忽略了快捷键的威力。在本文中&#xff0c;我们将详解Excel中的F1-F9快捷键&#xff0c;帮助您掌握实用的快捷操作&#xff0c;提升工作效…

leetcode(力扣)剑指 Offer 16. 数值的整数次方 (快速幂)

文章目录 题目描述思路分析完整代码 题目描述 实现 pow(x, n) &#xff0c;即计算 x 的 n 次幂函数&#xff08;即&#xff0c;xn&#xff09;。不得使用库函数&#xff0c;同时不需要考虑大数问题。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n 10 输出&#xff1a;10…

通向架构师的道路之Apache整合Tomcat

一、先从J2EE工程的通用架构说起 这是一个通用的Web即B/S工程的架构&#xff0c;它由&#xff1a; Web Server App Server DB Server 三大部分组成&#xff0c;其中&#xff1a; Web Server 置于企业防火墙外&#xff0c;这个防火墙&#xff0c;大家可以认为是…

c语言(函数)

目录 何为函数 库函数 自定义函数 二分查找数组下标 链式访问 函数的声明 函数定义 递归 正向打印数字 打印字符个数 使用临时变量 递归(不使用临时变量) n的阶乘 一般形式 递归 斐波那契数 递归 正常做法 何为函数 在计算机科学中&#xff0c;子程序是一个…

单片机外部晶振故障后自动切换内部晶振——以STM32为例

单片机外部晶振故障后自动切换内部晶振——以STM32为例 作者日期版本说明Dog Tao2023.08.02V1.0发布初始版本 文章目录 单片机外部晶振故障后自动切换内部晶振——以STM32为例背景外部晶振与内部振荡器STM32F103时钟系统STM32F407时钟系统 代码实现系统时钟设置流程时钟源检测…

spring AOP学习

概念 面向切面编程横向扩展动态代理 相关术语 动态代理 spring在运行期&#xff0c;生成动态代理对象&#xff0c;不需要特殊的编译器 Spring AOP的底层就是通过JDK动态代理或者CGLIb动态代理技术为目标Bean执行横向织入 目标对象实现了接口&#xff0c;spring使用JDK的ja…

Redis 集群 (cluster)

是什么 官网&#xff1a;Redis cluster specification | Redis 由于数据量过大&#xff0c;单个Master复制集难以承担&#xff0c;因此需要对多个复制集进行集群&#xff0c;形成水平扩展每个复制集只负责存储整个数据集的一部分&#xff0c;这就是Redis的集群&#xff0c;其作…

【机器学习】西瓜书习题3.5Python编程实现线性判别分析,并给出西瓜数据集 3.0α上的结果

参考代码 结合自己的理解&#xff0c;添加注释。 代码 导入相关的库 import numpy as np import pandas as pd import matplotlib from matplotlib import pyplot as plt导入数据&#xff0c;进行数据处理和特征工程 得到数据集 D { ( x i , y i ) } i 1 m , y i ∈ { 0 ,…

VR 变电站事故追忆反演——正泰电力携手图扑

VR(Virtual Reality&#xff0c;虚拟现实)技术作为近年来快速发展的一项新技术&#xff0c;具有广泛的应用前景&#xff0c;支持融合人工智能、机器学习、大数据等技术&#xff0c;实现更加智能化、个性化的应用。在电力能源领域&#xff0c;VR 技术在高性能计算机和专有设备支…

【机器学习】处理样本不平衡的问题

文章目录 样本不均衡的概念及影响样本不均衡的解决方法样本层面欠采样 &#xff08;undersampling&#xff09;过采样数据增强 损失函数层面模型层面采样集成学习 决策及评估指标 样本不均衡的概念及影响 机器学习中&#xff0c;样本不均衡问题经常遇到&#xff0c;比如在金融…

uniapp运行项目到iOS基座

2022年9月&#xff0c;因收到苹果公司警告&#xff0c;目前开发者已无法在iOS真机设备使用未签名的标准基座&#xff0c;所以现在要运行到 IOS &#xff0c;也需要进行签名。 Windows系统&#xff0c;HBuilderX 3.6.20以下版本&#xff0c;无法像MacOSX那样对标准基座进行签名…

选读SQL经典实例笔记16_逻辑否定

1. 示例数据 1.1. student insert into student values (1,AARON,20) insert into student values (2,CHUCK,21) insert into student values (3,DOUG,20) insert into student values (4,MAGGIE,19) insert into student values (5,STEVE,22) insert into student values (6…

伯俊ERP和金蝶云星空单据接口对接

伯俊ERP和金蝶云星空单据接口对接 对接源平台:金蝶云星空 金蝶K/3Cloud在总结百万家客户管理最佳实践的基础上&#xff0c;提供了标准的管理模式&#xff1b;通过标准的业务架构&#xff1a;多会计准则、多币别、多地点、多组织、多税制应用框架等&#xff0c;有效支持企业的运…

jenkins gitlab多分支构建发布

内容背景介绍 这个是新手教程,普及概念为主 公司现在还使用单分支发布测试环境和生产,多人协同开发同一个项目导致测试环境占用等待等情况 测试环境占用等待问题 测试环境代码直接合并到 master,容易导致误发布到生产的情况 避免多版本同时发布测试不完善的情况出现 中间件…

以CS32F031为例浅说国产32位MCU的内核处理器

芯片内核又称CPU内核&#xff0c;它是CPU中间的核心芯片&#xff0c;是CPU最重要的组成部分。由单晶硅制成&#xff0c;CPU所有的计算、接受/存储命令、处理数据都由核心执行。各种CPU核心都具有固定的逻辑结构&#xff0c;一级缓存、二级缓存、执行单元、指令级单元和总线接口…