设计模式之迭代器模式与命令模式详解和应用
目录
- 1 迭代器模式
- 1.1 目标
- 1.2 内容定位
- 1.3 迭代器模式
- 1.4 迭代器模式的应用场景
- 1.5 手写字定义的送代器
- 1.6 迭代器模式在源码中的体现
- 1.7 迭代器模式的优缺点
- 2 命令模式
- 2.1 定义
- 2.2 命令模式的应用场景
- 2.3 命令模式在业务场景中的应用
- 2.4 命令模式在源码中的体现
- 2.5 命令模式的优缺点
1 迭代器模式
1.1 目标
1、 了解迭代器模式和命令的应用场景。
2、 自己手写迭代器
3、 掌握迭代器模式和命令模式在源码中的应用,知其所以然。
1.2 内容定位
听说过迭代器模式和命令模式,但并不知其所以然的人群。
1.3 迭代器模式
迭代器模式( Iterator Pattern ) 又称为游标模式(Cursor Pattern), 它提供一种顺序访问集合/ 容器对象元素的方法,而又无须暴露集合内部表示。迭代器模式可以为不同的容器提供一致的 遍历行为,而不用关心容器内容元素组成结构,属于行为型模式。
原文 : Provide a way to access the elements of an aggregate object sequentially without exposing its under lying representation.
解释:提供一种顺序访问集合/容器对象元素的方法,而又无须暴露集合内部表示。
迭代器模式的本质是抽离集合对象迭代行为到迭代器中,提供一致访问接口。
1.4 迭代器模式的应用场景
迭代器模式在我们生活中应用的得也比较广泛,比如物流系统中的传送带,不管传送的是什 么物品,都被打包成一个一个的箱子并且有一个统一的二维码。这样我们不需要关心箱子里面 是啥,我们在分发时只需要一个一个检查发送的目的地即可。再比如,我们平时乘坐交通工具, 都是统一刷卡或者刷脸进站,而不需要关心是男性还是女性、是残疾人还是正常人等个性化的信息。

我们把多个对象聚在一起形成的总体称之为集合(Aggregate), 集合对象是能够包容一组对 象的容器对象。不同的集合其内部元素的聚合结构可能不同,而迭代器模式屏蔽了内部元素获 取细节,为外部提供一致的元素访问行为,解耦了元素迭代与集合对象间的耦合,并且通过提 供不同的迭代器,可以为同个集合对象提供不同顺序的元素访问行为,扩展了集合对象元素迭 代功能,符合开闭原则。迭代器模式适用于以下场景:
1、 访问一个集合对象的内容而无需暴露它的内部表示;
2、 为遍历不同的集合结构提供一个统一的访问接口。
首先来看下迭代器模式的通用UML类图:

从 UML类图中,我们可以看到,迭代器模式主要包含三种角色:
抽象迭代器( Iterator) : 抽象迭代器负责定义访问和遍历元素的接口 ;
具体迭代器( Concreteiterator) :提供具体的元素遍历行为;
抽象容器(Aggregate ) : 负责定义提供具体迭代器的接口 ;
具体容器(ConcreteAggregate ) :创建具体迭代器。
1.5 手写字定义的送代器
总体来说,迭代器模式还是非常简单的。我们还是以课程为例,下面我们自己创建一个课程的集合,集合中的每一个元素就是课程对象,然后自己手写一个迭代器,将每一个课程对象的信息读出来。
首先创建集合元素课程Course类 :
public class Course {private String name;public Course(String name) {this.name = name;}public String getName() {return name;}}
然后创建自定义迭代器Iterator接口 :
public interface Iterator<E> {E next();boolean hasNext();}
然后创建自定义的课程的集合ICourseAggregate接口 :
public interface ICourseAggregate {void add(Course course);void remove(Course course);Iterator<Course> iterator();}
然后,分别实现迭代器接口和集合接口,创建Iteratorlmpl实现类:
public class IteratorImpl<E> implements Iterator<E> {private List<E> list;private int cursor;private E element;public IteratorImpl(List<E> list) {this.list = list;}public E next() {System.out.print("当前位置 " + cursor + " : ");element = list.get(cursor);cursor ++;return element;}public boolean hasNext() {if(cursor > list.size() - 1){return false;}return true;}}
创建课程集合CourseAggregatelmpI 实现类:
public class CourseAggregateImpl implements ICourseAggregate {private List courseList;public CourseAggregateImpl() {this.courseList = new ArrayList();}public void add(Course course) {courseList.add(course);}public void remove(Course course) {courseList.remove(course);}public Iterator<Course> iterator() {return new IteratorImpl<Course>(courseList);}}
然后,编写客户端代码:
public class Test {public static void main(String[] args) {Course java = new Course("Java架构");Course javaBase = new Course("Java基础");Course design = new Course("设计模式");Course ai = new Course("人工智能");ICourseAggregate aggregate = new CourseAggregateImpl();aggregate.add(java);aggregate.add(javaBase);aggregate.add(design);aggregate.add(ai);System.out.println("===========课程列表==========");printCourse(aggregate);aggregate.remove(ai);System.out.println("===========删除操作之后的课程列表==========");printCourse(aggregate);}private static void printCourse(ICourseAggregate aggregate) {Iterator<Course> i = aggregate.iterator();while (i.hasNext()){Course course = i.next();System.out.println("《" + course.getName() + "》");}}}

运行结果如下:

看到这里,小伙伴们肯定会有一种似曾相识的感觉,让人不禁想起我们每天都在用的JDK 自带的结合迭代器。下面我们就来看看源码中是如何运用迭代器的。
1.6 迭代器模式在源码中的体现
先来看JDK中大家非常熟悉的Iterator源码 :
public interface Iterator<E> {boolean hasNext();E next();default void remove() {throw new UnsupportedOperationException("remove");}default void forEachRemaining(Consumer<? super E> action) {Objects.requireNonNull(action);while (hasNext())action.accept(next());}}
从上面代码中,我们看到两个主要的方法定义hasNext()和 next()方 法 ,和我们自己写的完 全一致。
另外,从上面的代码中,我们看到removeO方法实现似曾相识。其实是在组合模式中我们 见到过。迭代器模式和组合模式,两者似乎存在一定的相似性。组合模式解决的是统一树形结 构各层次访问接口,迭代器模式解决的是统一各集合对象元素遍历接口。虽然他们的适配场景 不同,但核心理念是相通的。
下面接看来看Iterator的实现类,其实在我们常用的ArrayList中有一个内部实现类Itr ,它 就实现了 Iterator接口 :
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{private class Itr implements Iterator<E> {int cursor; // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;public boolean hasNext() {return cursor != size;}@SuppressWarnings("unchecked")public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];}...}}
其中hasNextO方法和next()方法实现也非常简单,我们继续往下看在ArrayList内部还有 几个迭代器对Itr进行了进一步扩展,首先看Listltr :
private class ListItr extends Itr implements ListIterator<E> {ListItr(int index) {super();cursor = index;}public boolean hasPrevious() {return cursor != 0;}public int nextIndex() {return cursor;}public int previousIndex() {return cursor - 1;}...
}
它增加了 hasPreviousQ方法是否还有上一个等这样的判断。另外还有SubList对子集合的迭代处理。
当然,迭代器模式在MyBatis中也是必不可少的,来看一个Defaultcursor类 :
public class DefaultCursor<T> implements Cursor<T> {...private final CursorIterator cursorIterator = new CursorIterator();
}
首先它实现了 Cursor接 口 ,而且定义了一个成员变量cursoriterator , 我继续查看 Cursoriterator的源代码发现, 它 是 Defaultcursor的一个内部类,并且实现了 JDK中的 Iterater 接口。
1.7 迭代器模式的优缺点
优点:
1、 多态迭代:为不同的聚合结构提供一致的遍历接口,即一个迭代接口可以访问不同的集合对 象 ;
2、 简化集合对象接口 :迭代器模式将集合对象本身应该提供的元素迭代接口抽取到了迭代器中 ,使集合对象无须关心具体迭代行为;
3、 元素迭代功能多样化:每个集合对象都可以提供一个或多个不同的迭代器,使的同种元素聚合结构可以有不同的迭代行为;
4、解耦迭代与集合:迭代器模式 封装了具体的迭代算法,迭代算法的变化,不会影响到集合对象的架构。
缺点:
1、对于比较简单的遍历(像数组或者有序列表) ,使用迭代器方式遍历较为繁琐。 在日常开发当中,我们几乎不会自己写迭代器。除非我们需要定制一个自己实现的数据结构 对应的迭代器,否则,开源框架提供给我们的API完全够用。
2 命令模式
2.1 定义
命令模式(Command Pattern )是对命令的封装,每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式解耦了请求方和接收方,请求方只需请求执行命令,不用关心命令是怎样被接收,怎样被操作以及是否被执行…等。 命令模式属于行为型模式。
原 文 : Encapsulate a request as an object, there by letting you parameterize clients with different requests, queue or log requests,and support undoable operations.
解释:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
在软件系统中,行为请求者与行为实现者通常是一种紧耦合关系,因为这样的实现简单明了。 但紧耦合关系缺乏扩展性,在某些场合中,当需要为行为进行记录,撤销或重做等处理时,只 能修改源码。而命令模式通过为请求与实现间引入一个抽象命令接口,解耦了请求与实现,并 且中间件是抽象的,它可以有不同的子类实现,因此其具备扩展性。所以,命令模式的本质是 解耦命令请求与处理。
2.2 命令模式的应用场景
当系统的某项操作具备命令语义时,且命令实现不稳定(变化),那么可以通过命令模式解耦请求与实现,利用抽象命令接口使请求方代码架构稳定,封装接收方具体命令实现细节。接收方与抽象命令接口呈现弱耦合(内部方法无需一致),具备良好的扩展性。
命令模式适用于 以下应用场景:
1、现实语义中具备"命令"的操作(如命令菜单,shell命令…);
2、请求调用者和请求的接收者需要解耦,使得调用者和接收者不直接交互;
3、需要抽象出等待执行的行为,比如撤销(Undo)操作和恢复(Redo)等操作;
4、需要支持命令宏(即命令组合操作)。
首先看下命令模式的通用UML类图:

从 UML类图中,我们可以看到,命令模式 主要包含四种角色:
接收者角色(Receiver):该类负责具体实施或执行一个请求;
命令角色(Command ):定义需要执行的所有命令行为;
具体命令角色(Concrete Command )该类内部维护一个接收者(Receiver ),在其execute() 方法中调用Receiver的相关方法;
请求者角色(Invoker):接收客户端的命令,并执行命令。
从命令模式的UML类图中,其实可以很清晰地看出:Command的出现就是作为Receiver 和 Invoker的中间件,解耦了彼此。而之所以引入Command中间件,我觉得是以下两方面原因 :
解耦请求与实现:即解耦了 Invoker和 Receiver , 因为在UML类图中,Invoker是一个具 体的实现,等待接收客户端传入命令(即 Invoker与客户端耦合),Invoker处于业务逻辑区域, 应当是一个稳定的结构。而 Receiver是属于业务功能模块 是经常变动的 如果没有Command z 则 Invoker紧耦合Receiver , 一个稳定的结构依赖了一个不稳定的结构,就会导致整个结构都不稳定了。这也就是Command引入的原因:不仅仅是解耦请求与实现,同时稳定( Invoker) 依赖稳 定 (Command ),结构还是稳定的。
扩展性增强:扩展性体现在两个方面:
1、 Receiver属于底层细节,可以通过更换不同的Receiver达到不同的细节实现;
2、 Command接口本身就是抽象的,本身就具备扩展性;而且由于命令对象本身就具备抽 象 ,如果结合装饰器模式,功能扩展简直如鱼得水。
注:在一个系统中,不同的命令对应不同的请求,也就是说无法把请求抽象化,因此命令模式中的Receiver是具体实 现;但是如果在某一个模块中,可以对Receiver进行抽象,其实这就变相使用到了桥接模式(Command类具备两个变 化的维度:Command和 Receiver), 这样子的扩展性会更加优秀。
举个生活中的例子,相信80后的小伙伴应该都经历过普及黑白电视机的那个年代。黑白电 视机要换台那简直不容易,需要人跑上前去用力掰动电视机上那个切换频道的旋钮,一 顿 〃啪 啪啪〃折腾下来才能完成一次换台。如今时代好了,我们只需躺沙发上按一下遥控器就完成了 换台。这就是用到了命令模式,将换台命令和换台处理进行了分离。
另外,就是餐厅的点菜单,一般是后厨先把所有的原材料组合配置好了,客户用餐前只需要 点菜即可,将需求和处理进行了解耦。
2.3 命令模式在业务场景中的应用
假如我们自己开发一个播放器,播放器有播放功能、有拖动进度条功能、停止播放功能、暂 停功能,我们自己去操作播放器的时候并不是直接调用播放器的方法,而是通过一个控制条去传达指令给播放器内核,那么具体传达什么指令,会被封装为一个一个的按钮。那么每个按钮 的就相当于是对一条命令的封装。用控制条实现了用户发送指令与播放器内核接收指令的解耦。
下面来看代码,首先创建播放器内核GPlayer类:
public class GPlayer {public void play(){System.out.println("正常播放");}public void speed(){System.out.println("拖动进度条");}public void stop(){System.out.println("停止播放");}public void pause(){System.out.println("暂停播放");}
}
创建命令接口 IAction类:
public interface IAction {void execute();
}
然后分别创建操作播放器可以接受的指令,播放指令PlayAction类 :
public class PlayAction implements IAction {private GPlayer gplayer;public PlayAction(GPlayer gplayer) {this.gplayer = gplayer;}public void execute() {gplayer.play();}
}
暂停指令PauseAction类 :
public class PauseAction implements IAction {private GPlayer gplayer;public PauseAction(GPlayer gplayer) {this.gplayer = gplayer;}public void execute() {gplayer.pause();}
}
拖动进度条指令SpeedAction类 :
public class SpeedAction implements IAction {private GPlayer gplayer;public SpeedAction(GPlayer gplayer) {this.gplayer = gplayer;}public void execute() {gplayer.speed();}
}
停止播放指令StopAction类 :
public class StopAction implements IAction {private GPlayer gplayer;public StopAction(GPlayer gplayer) {this.gplayer = gplayer;}public void execute() {gplayer.stop();}
}
最后 ,创建控制条Controller类 :
public class Controller {private List<IAction> actions = new ArrayList<IAction>();public void addAction(IAction action){actions.add(action);}public void execute(IAction action){action.execute();}public void executes(){for (IAction action:actions) {action.execute();}actions.clear();}
}
从上面代码来看,控制条可以执行单条命令,也可以批量执行多条命令。下面来看客户端测试代码:
public class Test {public static void main(String[] args) {GPlayer player = new GPlayer();Controller controller = new Controller();controller.execute(new PlayAction(player));controller.addAction(new PauseAction(player));controller.addAction(new PlayAction(player));controller.addAction(new StopAction(player));controller.addAction(new SpeedAction(player));controller.executes();}
}
运行效果如下:
正常播放
暂停播放
正常播放
停止播放
拖动进度条
由于控制条已经与播放器内核解耦了,以后如果想扩展新命令,只需增加命令即可,控制条 的结构无需改动。
2.4 命令模式在源码中的体现
首先来看JDK中的Runnable接口 ,实际上Runnable就相当于是命令的抽象,只要是实现 了 Runnable接口的类都被认为是一个线程。
public interface Runnable { public abstract void run();
}
实际上调用线程的start()方法之后,就有资格去抢CPU资源,而不需要我们自己编写获得 CPU资源的逻辑。而线程抢到CPU资源后,就会执行run()方法中的内容,用 Runnable接口 把用户请求和CPU执行进行了解耦。
然 后 ,再看一个大家非常孰悉的junit.framework.Test接口 :
package junit.framework;
public interface Test { public abstract int countTestCases(); public abstract void run(TestResult result);
}
Test接口中有两个方法,第一个是countTestCases()方法用来统计当前需要执行的测试用例 总数。第二个是run()方法就是用来执行具体的测试逻辑,其参数TestResult是用来返回测试结果的。 实际上我们在平时编写测试用例的时候,只需要实现Test接口即便认为就是一个测试用例,那 么在执行的时候就会自动识别。实际上我们平时通常做法都是继承TestCase类 ,我们不妨来看 —下 TestCase的源码:
public abstract class TestCase extends Assert implements Test { ...public void run(TestResult result) { result.run(this);}...
}
实际上TestCase类它也实现了 Test接口。我们继承TestCase类 ,相当于也实现了 Test 接口,自然也就会被扫描成为一个测试用例。
2.5 命令模式的优缺点
优点:
1、通过引入中间件(抽象接口),解耦了命令请求与实现;
2、 扩展性良好,可以很容易地增加新命令;
3、 支持组合命令,支持命令队列;
4、可以在现有命令的基础上,增加额外功能(比如日志记录…,结合装饰器模式更酸爽)。
缺点:
1、 具体命令类可能过多;
2、 命令模式的结果其实就是接收方的执行结果,但是为了以命令的形式进行架构,解耦请求与 实现,引入了额外类型结构(引入了请求方与抽象命令接口),增加了理解上的困难(不过这 也是设计模式带来的一个通病,抽象必然会引入额外类型;抽象肯定比紧密难理解)。
相关文章:
设计模式之迭代器模式与命令模式详解和应用
目录1 迭代器模式1.1 目标1.2 内容定位1.3 迭代器模式1.4 迭代器模式的应用场景1.5 手写字定义的送代器1.6 迭代器模式在源码中的体现1.7 迭代器模式的优缺点2 命令模式2.1 定义2.2 命令模式的应用场景2.3 命令模式在业务场景中的应用2.4 命令模式在源码中的体现2.5 命令模式的…...
【QA】[Vue/复选框全选] v-model绑定每一项的赋初值问题
发生场景:不只是复选框的状态改变,还有的功能要用到复选框的选中状态,比如:购物车计算总价,合计等等。 引入:复选框 checkbox 在使用时,需要用v-model绑定布尔值,来获取选中状态&…...
python基于django+vue微信小程序的校园二手闲置物品交易
在大学校园里,存在着很多的二手商品,但是由于信息资源的不流通以及传统二手商品信息交流方式的笨拙,导致了很多仍然具有一定价值或者具有非常价值的二手商品的囤积,乃至被当作废弃物处理。现在通过微信小程序的校园二手交易平台,可以方便快捷的发布和交流任何二手商品的信息,并…...
设计模式之观察者模式
什么是观察者模式 观察者模式定义了对象之间一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都能收到通知并自动刷新。 观察者模式主要包含以下几个角色: Subject(目标):指被观察的对…...
Java Lambda表达式
目录1 Lambda表达式1.1 函数式编程思想概括1.2 Lambda表达式标准格式1.3 Lambda表达式练习1(抽象方法无参无返回值)1.4 Lambda表达式练习2(抽象方法带参无返回值)1.5 Lambda表达式练习2(抽象方法带参带返回值ÿ…...
【1237. 找出给定方程的正整数解】
来源:力扣(LeetCode) 描述: 给你一个函数 f(x, y) 和一个目标结果 z,函数公式未知,请你计算方程 f(x,y) z 所有可能的正整数 数对 x 和 y。满足条件的结果数对可以按任意顺序返回。 尽管函数的具体式子…...
java基础学习 day41(继承中成员变量和成员方法的访问特点,方法的重写)
继承中,成员变量的访问特点 a. name前什么都不加,name变量的访问采用就近原则,先在局部变量中查找,若没找到,继续在本类的成员变量中查找,若没找到,继续在直接父类的成员变量中查找,…...
【c语言进阶】深度剖析整形数据
🚀write in front🚀 📜所属专栏: 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对我最大的激励…...
【信息系统项目管理师】项目管理十大知识领域记忆敲出(采购风险沟通干系人)
【信息系统项目管理师】项目管理十大知识领域记忆敲出(采购风险沟通干系人) 这里写目录标题【信息系统项目管理师】项目管理十大知识领域记忆敲出(采购风险沟通干系人)一.项目采购管理记忆敲出1.合同管理:2.规划采购管…...
[LeetCode 1237]找出给定方程的正整数解
题目描述 题目链接:[LeetCode 1237]找出给定方程的正整数解 给你一个函数 f(x, y) 和一个目标结果 z,函数公式未知,请你计算方程 f(x,y) z 所有可能的正整数 数对 x 和 y。满足条件的结果数对可以按任意顺序返回。 尽管函数的具体式子未知…...
6.2 构建 RESTful 应用接口
第6章 构建 RESTful 服务 6.1 RESTful 简介 6.2 构建 RESTful 应用接口 6.3 使用 Swagger 生成 Web API 文档 6.4 实战:实现 Web API 版本控制 6.2 构建 RESTful 应用接口 6.2.1 Spring Boot 对 RESTful 的支持 Spring Boot 提供的spring-boot-starter-web组件完全…...
20230218英语学习
How Italian Artist’s Mild Colors Dominate World of Design 温柔的“莫兰迪色”,如何引领设计时尚? The Morandi color scheme has become an across-the-board fashion that now prevails in the world of design.Soft and sophisticated Morandi c…...
Linux单一服务管理systemctl
基本上systemd这个启动服务机制只有systemctl命令来处理,所以全部的操作都需要使用systemctl systemctl管理单一服务 一般来说服务的启动有两个阶段,一个是开机是否启动,以及现在是否启动 systemctl【command】【unit】 command主要有&…...
【GStreamer 】 TX1中CPU和GPU解码显示海康相机RTSP流
大家好,我是虎哥,今天找了一套海康的相机,想后续测试一下DeepStream用网络相机RTSP流做输入看看后续目标识别和分类。但是还是想先实时看看视频,当然,可以选择VLC去查看,顺道我也用GStreamer 来测试了一下&…...
匿名内部类、Lambda表达式、方法引用对比分析
文章目录一、匿名内部类1. 语法格式2. 使用方法① 传统方式② 匿名内部类方式二、Lambda表达式1. 语法格式2. 使用方法① 匿名内部类方式② Lambda表达式方式三、方法引用1. 语法格式2. 使用方法① 类型的静态方法引用② 类型的构造方法引用③ 类型的实例方法引用④ 对象的实例…...
ESXi主机CVE-2021-21972漏洞复现安全处置建议
一、漏洞简介 vSphere 是 VMware 推出的虚拟化平台套件,包含 ESXi、vCenter Server 等一系列的软件。其中 vCenter Server 为 ESXi 的控制中心,可从单一控制点统一管理数据中心的所有 vSphere 主机和虚拟机。 vSphere Client(HTML5…...
研报精选230217
目录 【行业230217毕马威】奢侈品行业新气象【行业230217国信证券】医药生物行业2023年2月投资策略:持续关注疫后复苏和创新两大主线【行业230217国金证券】航空锻造:稳定格局筑专业化壁垒,顺势而为拓产业链深度【个股230217西南证券_招商轮船…...
c++11 标准模板(STL)(std::unordered_set)(一)
定义于头文件 <unordered_set> template< class Key, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator<Key> > class unordered_set;(1)(C11 起)namespace pmr { templ…...
【C语言进阶】你听说过柔性数组吗?
👦个人主页:Weraphael ✍🏻作者简介:目前是C语言学习者 ✈️专栏:C语言航路 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞&a…...
[LeetCode]1237. 找出给定方程的正整数解
题目链接:https://leetcode.cn/problems/find-positive-integer-solution-for-a-given-equation/description/ 题目描述: 样例1: 输入:function_id 1, z 5 输出:[[1,4],[2,3],[3,2],[4,1]] 解释:functi…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
