瑞_23种设计模式_状态模式

文章目录

    • 1 状态模式(State Pattern)
      • 1.1 介绍
      • 1.2 概述
      • 1.3 状态模式的结构
      • 1.4 状态模式的优缺点
      • 1.5 状态模式的使用场景
    • 2 案例一
      • 2.1 需求
      • 2.2 代码实现(未使用状态模式)
      • 2.3 代码实现(状态模式)
    • 3 案例二
      • 3.1 需求
      • 3.2 代码实现

🙊 前言:本文章为瑞_系列专栏之《23种设计模式》的状态模式篇。本文中的部分图和概念等资料,来源于博主学习设计模式的相关网站《菜鸟教程 | 设计模式》和《黑马程序员Java设计模式详解》,特此注明。本文中涉及到的软件设计模式的概念、背景、优点、分类、以及UML图的基本知识和设计模式的6大法则等知识,建议阅读 《瑞_23种设计模式_概述》

本系列 - 设计模式 - 链接:《瑞_23种设计模式_概述》

⬇️本系列 - 创建型模式 - 链接🔗

  单例模式:《瑞_23种设计模式_单例模式》
  工厂模式:《瑞_23种设计模式_工厂模式》
  原型模式:《瑞_23种设计模式_原型模式》
抽象工厂模式:《瑞_23种设计模式_抽象工厂模式》
 建造者模式:《瑞_23种设计模式_建造者模式》

⬇️本系列 - 结构型模式 - 链接🔗

  代理模式:《瑞_23种设计模式_代理模式》
 适配器模式:《瑞_23种设计模式_适配器模式》
 装饰者模式:《瑞_23种设计模式_装饰者模式》
  桥接模式:《瑞_23种设计模式_桥接模式》
  外观模式:《瑞_23种设计模式_外观模式》
  组合模式:《瑞_23种设计模式_组合模式》
  享元模式:《瑞_23种设计模式_享元模式》

⬇️本系列 - 行为型模式 - 链接🔗

模板方法模式:《瑞_23种设计模式_模板方法模式》
  策略模式:《瑞_23种设计模式_策略模式》
  命令模式:《瑞_23种设计模式_命令模式》
 职责链模式:《瑞_23种设计模式_职责链模式》
  状态模式:《后续更新》
 观察者模式:《后续更新》
 中介者模式:《后续更新》
 迭代器模式:《后续更新》
 访问者模式:《后续更新》
 备忘录模式:《后续更新》
 解释器模式:《后续更新》

在这里插入图片描述

1 状态模式(State Pattern)

瑞:状态模式堆程序员水平要求较高,使用有点困难,属于提升模式。可用于简化复杂的条件语句(如一个操作中含有庞大的分支结构,即长的 if-else 链或 switch case),并且这些分支决定于对象的状态。

  在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。

  瑞:行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。
  瑞:行为型模式分为类行为模式对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性

状态模式属于:对象行为模式

  在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。

1.1 介绍

  • 意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

  • 主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。

  • 何时使用代码中包含大量与对象状态有关的条件语句

  • 如何解决:将各种具体的状态类抽象出来。

  • 关键代码:通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法。而且,状态模式的实现类的方法,一般返回值,或者是改变实例变量的值。也就是说,状态模式一般和对象的状态有关。实现类的方法有不同的功能,覆盖接口中的方法。状态模式和策略模式一样,也可以用于消除 if…else 等条件选择语句。

  • 应用实例
      1️⃣ 打篮球的时候运动员可以有正常状态、不正常状态和超常状态。
      2️⃣ 曾侯乙编钟中,“钟是抽象接口”,“钟A”等是具体状态,“曾侯乙编钟”是具体环境(Context)。

  • 优点
      1️⃣ 封装了转换规则。
      2️⃣枚举可能的状态,在枚举状态之前需要确定状态种类。
      3️⃣ 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
      4️⃣ 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
      5️⃣ 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

  • 缺点
      1️⃣ 状态模式的使用必然会增加系统类和对象的个数。
      2️⃣ 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
      3️⃣ 状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

  • 使用场景
      1️⃣ 行为随状态改变而改变的场景。
      2️⃣ 条件、分支语句的代替者。

  • 注意事项:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。

1.2 概述

定义:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

  状态模式通过将每个状态的行为封装在各自的类中,使得对象可以在运行时根据其内部状态的变化而改变行为,从而提供了一种优雅的方式来组织和管理复杂的状态转换逻辑。

  使用状态模式的好处是可以简化复杂的条件语句(如长的 if-else 链),使得代码更加清晰和易于维护。此外,当新的状态需要添加到系统中时,只需要增加一个新的具体状态类,而不需要修改环境类或其他状态类,这有助于保持系统的灵活性和可扩展性。

1.3 状态模式的结构

  • 状态模式主要包含以下角色:
      1️⃣ 环境(Context)角色:也称为上下文,它定义了客户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
      2️⃣ 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
      3️⃣ 具体状态(Concrete State)角色:实现抽象状态所对应的行为。

1.4 状态模式的优缺点

优点

  • 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  • 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。

缺点

  • 状态模式的使用必然会增加系统类和对象的个数。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  • 状态模式对"开闭原则"的支持并不太好。

1.5 状态模式的使用场景

  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
  • 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。



2 案例一

【案例】电梯状态控制

2.1 需求

  通过按钮来控制一个电梯的状态,一个电梯有开门状态,关门状态,停止状态,运行状态。每一种状态改变,都有可能要根据其他状态来更新处理。例如,如果电梯门现在处于运行时状态,就不能进行开门操作,而如果电梯门是停止状态,就可以执行开门操作。

  该案例未使用状态模式设计的类图如下:

在这里插入图片描述

(图为未使用状态模式前)

2.2 代码实现(未使用状态模式)

电梯接口(接口)
/*** 电梯接口** @author LiaoYuXing-Ray**/
public interface ILift {// 定义四个电梯状态的常量int OPENING_STATE = 1;int CLOSING_STATE = 2;int RUNNING_STATE = 3;int STOPPING_STATE = 4;// 设置电梯状态的功能void setState(int state);// 电梯操作功能void open();void close();void run();void stop();
}
电梯类(类)

/*** 电梯类(ILift的子实现类)** @author LiaoYuXing-Ray**/
public class Lift implements ILift {// 声明一个记录当前电梯的状态private int state;public void setState(int state) {this.state = state;}public void open() {switch (state) { // 当前电梯状态case OPENING_STATE :// 什么事都不做break;case CLOSING_STATE :System.out.println("电梯打开了...");// 设置当前电梯状态为开启状态setState(OPENING_STATE);break;case STOPPING_STATE :System.out.println("电梯打开了...");// 设置当前电梯状态为开启状态setState(OPENING_STATE);break;case RUNNING_STATE :// 什么事都不做break;}}public void close() {switch (this.state) {case OPENING_STATE:System.out.println("电梯关门了。。。"); // 只有开门状态可以关闭电梯门,可以对应电梯状态表来看this.setState(CLOSING_STATE); // 关门之后电梯就是关闭状态了break;case CLOSING_STATE:// do nothing // 已经是关门状态,不能关门break;case RUNNING_STATE:// do nothing // 运行时电梯门是关着的,不能关门break;case STOPPING_STATE:// do nothing // 停止时电梯也是关着的,不能关门break;}}public void run() {switch (this.state) {case OPENING_STATE: // 电梯不能开着门就走// do nothingbreak;case CLOSING_STATE: // 门关了,可以运行了System.out.println("电梯开始运行了。。。");this.setState(RUNNING_STATE); // 现在是运行状态break;case RUNNING_STATE:// do nothing 已经是运行状态了break;case STOPPING_STATE:System.out.println("电梯开始运行了。。。");this.setState(RUNNING_STATE);break;}}public void stop() {switch (this.state) {case OPENING_STATE: // 开门的电梯已经是是停止的了(正常情况下)// do nothing break;case CLOSING_STATE: // 关门时才可以停止System.out.println("电梯停止了。。。");this.setState(STOPPING_STATE);break;case RUNNING_STATE: // 运行时当然可以停止了System.out.println("电梯停止了。。。");this.setState(STOPPING_STATE);break;case STOPPING_STATE:// do nothingbreak;}}
}
测试类
/*** 测试类** @author LiaoYuXing-Ray**/
public class Client {public static void main(String[] args) {// 创建电梯对象Lift lift = new Lift();/*设置当前电梯的状态*/lift.setState(ILift.OPENING_STATE);lift.open();lift.close();lift.run();lift.stop();System.out.println("\n=== 我是一条华丽的分割线 ===\n");lift.setState(ILift.CLOSING_STATE);lift.open();lift.close();lift.run();lift.stop();System.out.println("\n=== 我是一条华丽的分割线 ===\n");lift.setState(ILift.RUNNING_STATE);lift.open();lift.close();lift.run();lift.stop();System.out.println("\n=== 我是一条华丽的分割线 ===\n");lift.setState(ILift.STOPPING_STATE);lift.open();lift.close();lift.run();lift.stop();}
}

  代码运行结果如下:

	电梯关门了。。。电梯开始运行了。。。电梯停止了。。。=== 我是一条华丽的分割线 ===电梯打开了...电梯关门了。。。电梯开始运行了。。。电梯停止了。。。=== 我是一条华丽的分割线 ===电梯停止了。。。=== 我是一条华丽的分割线 ===电梯打开了...电梯关门了。。。电梯开始运行了。。。电梯停止了。。。

问题分析:

  • 使用了大量的switch…case这样的判断(if…else也是一样),使程序的可阅读性变差。
  • 扩展性很差。如果新加了断电的状态,我们需要修改上面判断逻辑

2.3 代码实现(状态模式)

  对上述电梯的案例使用状态模式进行改进。类图如下:

在这里插入图片描述

抽象状态类(抽象类)
/*** 抽象状态类** @author LiaoYuXing-Ray**/
public abstract class LiftState {// 声明环境角色类变量protected Context context;public void setContext(Context context) {this.context = context;}// 电梯开启操作public abstract void open();// 电梯关闭操作public abstract void close();// 电梯运行操作public abstract void run();// 电梯停止操作public abstract void stop();
}
电梯开启状态类(类)
/*** 电梯开启状态类** @author LiaoYuXing-Ray**/
public class OpeningState extends LiftState {// 当前状态要执行的方法public void open() {System.out.println("电梯开启。。。");}public void close() {// 修改状态super.context.setLiftState(Context.CLOSING_STATE);// 调用当前状态中的context中的close方法super.context.close();}public void run() {// 什么都不做}public void stop() {// 什么都不做}
}
电梯运行状态类(类)
/*** 电梯运行状态类** @author LiaoYuXing-Ray**/
public class RunningState extends LiftState {// 运行的时候开电梯门?你疯了!电梯不会给你开的@Overridepublic void open() {// do nothing}// 电梯门关闭?这是肯定了@Overridepublic void close() {// 虽然可以关门,但这个动作不归我执行// do nothing}// 这是在运行状态下要实现的方法@Overridepublic void run() {System.out.println("电梯正在运行...");}// 这个事绝对是合理的,光运行不停止还有谁敢做这个电梯?!估计只有上帝了@Overridepublic void stop() {super.context.setLiftState(Context.STOPPING_STATE);super.context.stop();}
}
电梯停止状态类(类)
/*** 电梯停止状态类** @author LiaoYuXing-Ray**/
public class StoppingState extends LiftState {// 停止状态,开门,那是要的!@Overridepublic void open() {// 状态修改super.context.setLiftState(Context.OPENING_STATE);// 动作委托为CloseState来执行,也就是委托给了ClosingState子类执行这个动作super.context.getLiftState().open();}// 虽然可以关门,但这个动作不归我执行@Overridepublic void close() {// 状态修改super.context.setLiftState(Context.CLOSING_STATE);// 动作委托为CloseState来执行,也就是委托给了ClosingState子类执行这个动作super.context.getLiftState().close();}// 停止状态再跑起来,正常的很@Overridepublic void run() {// 状态修改super.context.setLiftState(Context.RUNNING_STATE);// 动作委托为CloseState来执行,也就是委托给了ClosingState子类执行这个动作super.context.getLiftState().run();}// 停止状态是怎么发生的呢?当然是停止方法执行了@Overridepublic void stop() {System.out.println("电梯停止了...");}
}
电梯关闭状态类(类)
/*** 电梯关闭状态类** @author LiaoYuXing-Ray**/
public class ClosingState extends LiftState {// 电梯门关闭,这是关闭状态要实现的动作@Overridepublic void close() {System.out.println("电梯门关闭...");}// 电梯门关了再打开@Overridepublic void open() {super.context.setLiftState(Context.OPENING_STATE);super.context.open();}// 电梯门关了就跑,这是再正常不过了@Overridepublic void run() {super.context.setLiftState(Context.RUNNING_STATE);super.context.run();}// 电梯门关着,我就不按楼层@Overridepublic void stop() {super.context.setLiftState(Context.STOPPING_STATE);super.context.stop();}
}
环境角色类(类)
/*** 环境角色类** @author LiaoYuXing-Ray**/
public class Context {// 定义对应状态对象的常量public final static OpeningState OPENING_STATE = new OpeningState();public final static ClosingState CLOSING_STATE = new ClosingState();public final static RunningState RUNNING_STATE = new RunningState();public final static StoppingState STOPPING_STATE = new StoppingState();// 定义一个当前电梯状态变量private LiftState liftState;public LiftState getLiftState() {return liftState;}// 设置当前状态对象public void setLiftState(LiftState liftState) {this.liftState = liftState;// 设置当前状态对象中的Context对象this.liftState.setContext(this);}public void open() {this.liftState.open();}public void close() {this.liftState.close();}public void run() {this.liftState.run();}public void stop() {this.liftState.stop();}
}
测试类
/*** 测试类** @author LiaoYuXing-Ray**/
public class Client {public static void main(String[] args) {// 创建环境角色对象Context context = new Context();/*设置当前电梯装填*/context.setLiftState(new OpeningState());context.open();context.run();context.close();context.stop();System.out.println("\n=== 我是一条华丽的分割线 ===\n");context.setLiftState(new RunningState());context.open();context.run();context.close();context.stop();System.out.println("\n=== 我是一条华丽的分割线 ===\n");context.setLiftState(new StoppingState());context.open();context.run();context.close();context.stop();System.out.println("\n=== 我是一条华丽的分割线 ===\n");context.setLiftState(new ClosingState());context.open();context.run();context.close();context.stop();}
}

  代码运行结果如下:

	电梯开启。。。电梯门关闭...电梯停止了...=== 我是一条华丽的分割线 ===电梯正在运行...电梯停止了...=== 我是一条华丽的分割线 ===电梯开启。。。电梯门关闭...电梯停止了...=== 我是一条华丽的分割线 ===电梯开启。。。电梯门关闭...电梯停止了...

3 案例二

本案例为菜鸟教程中的案例

3.1 需求

  我们将创建一个 State 接口和实现了 State 接口的实体状态类。Context 是一个带有某个状态的类。StatePatternDemo,我们的演示类使用 Context 和状态对象来演示 Context 在状态改变时的行为变化。

在这里插入图片描述

3.2 代码实现

步骤 1

  创建一个接口。

State.java
public interface State {public void doAction(Context context);
}

步骤 2

  创建实现接口的实体类。

StartState.java
public class StartState implements State {public void doAction(Context context) {System.out.println("Player is in start state");context.setState(this); }public String toString(){return "Start State";}
}
StopState.java
public class StopState implements State {public void doAction(Context context) {System.out.println("Player is in stop state");context.setState(this); }public String toString(){return "Stop State";}
}

步骤 3

  创建 Context 类。

Context.java
public class Context {private State state;public Context(){state = null;}public void setState(State state){this.state = state;     }public State getState(){return state;}
}

步骤 4

  使用 Context 来查看当状态 State 改变时的行为变化。

StatePatternDemo.java
public class StatePatternDemo {public static void main(String[] args) {Context context = new Context();StartState startState = new StartState();startState.doAction(context);System.out.println(context.getState().toString());StopState stopState = new StopState();stopState.doAction(context);System.out.println(context.getState().toString());}
}

步骤 5

  执行程序,输出结果:

	Player is in start stateStart StatePlayer is in stop stateStop State



本文是博主的粗浅理解,可能存在一些错误或不完善之处,如有遗漏或错误欢迎各位补充,谢谢

  如果觉得这篇文章对您有所帮助的话,请动动小手点波关注💗,你的点赞👍收藏⭐️转发🔗评论📝都是对博主最好的支持~


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

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

相关文章

[BT]BUUCTF刷题第4天(3.22)

第4天(共两题) Web [极客大挑战 2019]Upload 这是文件上传的题目,有一篇比较详细的有关文件上传的绕过方法文件上传漏洞详解(CTF篇) 首先直接上传带一句话木马的php文件,发现被拦截,提示不是图…

Linux安装Nacos

安装前必要准备 准备Java环境 ,8以上的版本,mysql(集群相关信息),nginx(进行代理) 安装Nacos 首先我们要有一个nacos的包,我们可以在线下载,也可以提前下载好&#xf…

Nginx 全局块配置 worker 进程的两个指令

1. 前言 熟悉 nginx 运行原理的都知道,nginx 服务启动后,会有一个 master 进程和多个 worker 进程,master 进程负责管理所有的 worker 进程,worker 进程负责处理和接收用户请求 在这里我们所要研究的是 master 进程一定要创建 wo…

如何进行设备的非对称性能测试

非对称性能测试介绍 RFC2544是RFC组织提出的用于评测网络互联设备(防火墙、IDS、Switch等)的国际标准。主要是对RFC1242中定义的性能评测参数的具体测试方法、结果的提交形式作了较详细的规定。标准中定义了4个重要的参数:吞吐量&#xff08…

Uni-app/Vue/Js本地模糊查询,匹配所有字段includes和some方法结合使用e

天梦星服务平台 (tmxkj.top)https://tmxkj.top/#/ 1.第一步 需要一个数组数据 {"week": "全部","hOutName": null,"weekendPrice": null,"channel": "门市价","hOutId": 98,"cTime": "…

打造新质生产力,亚信科技2024年如何行稳致远?

引言:不冒进、不激进,稳扎稳打, 一个行业一个行业地深度拓展。 【全球云观察 | 科技热点关注】 基于以往“一巩固、三发展”的多年业务战略,亚信科技正在落实向非通信行业、标准产品、软硬一体产品和国际市场的“四…

Spring异步注解@Async线程池配置

系列文章目录 文章目录 系列文章目录前言前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 从Spring3开始提供了@Async注解,该注解可以被标注在方法上,以便异步地调…

多段智能功率分配,双设备同时快充,乐得瑞LDR6020 一分拖二PD 快充线方案

随着移动设备的普及和功能的日益增强,电池续航成为了用户关注的重点之一。为了满足用户对于快速充电的需求,各大厂商纷纷推出了各种快充技术和产品。在这个背景下,乐得瑞公司推出了一款名为LDR6020的一分二PD快充线方案,该方案采用…

处理登录失效后提示多个错误

问题: 我的场景是后端规定,即使登录失效返回的code仍是200,然后data的code是999什么的; 原本代码: 修改版代码: 通过节 const NotLoginEvent () > {router.replace("/login");localStorage.clear();M…

python的ITS 信息平台的设计与实现flask-django-nodejs-php

第二,陈列说明该系统实现所采用的架构、系统搭建采用的服务器、系统开发环境和使用的工具,以及系统后台采用的数据库。 最后,对系统进行全面测试,主要包括功能测试、查询性能测试、安全性能测试。 分析系统存在的不足以及将来改进…

ios symbolicatecrash 符号化crash

一、准备 1.1 .crash 文件获取 设备连接电脑 打开XCode, 依次 XCode -> Windows -> Device and Simulator -> Open Recent Logs 找到 (对应app名+时间点) -> 右键 Show in Finder 1.2 .dSYM 和 .app 文件获取 .dSYM是十六进制函数地址映射信息的中转文件,调试的…

中国光伏展

河北省京津冀国际光伏展是一场专注于光伏产业的展览会。作为中国光伏行业的重要展会之一,该展会旨在推动京津冀地区光伏产业的发展,促进光伏技术的交流与合作。 光伏展将汇集来自国内外的光伏企业、科研机构、专家学者等相关人士,展示最新的光…

Jetson AGX ORIN 配置 FGVC-PIM 神经网络

Jetson AGX ORIN 配置 FGVC-PIM 神经网络 文章目录 Jetson AGX ORIN 配置 FGVC-PIM 神经网络配置 ORIN 环境创建 FGVC-PIM 虚拟环境安装 PyTorch安装 torchvision安装其他依赖包 配置 ORIN 环境 首先先配置 ORIN 的环境,可以参考这个链接: Jetson AGX …

nuclei使用方法

nuclei使用方法 查看帮助 nuclei -h 列出所有模板 nuclei -tl 查找某种cms的相关漏洞模板,wordpress为例 nuclei -tl -tc "contains(name,wordpress)"便会列出内容里含有wordpress关键字的漏洞检测模板 使用与某cms相关的所有漏洞模板进行扫描&#…

基于Lealfet.js展示Turf.js生成的平滑曲线实践

目录 前言 一、问题的由来 1、创建网页框架 2、创建map对象 3、构建点位,生成路线 二、Turf.js平滑曲线改造 1、官网方法介绍 2、0.4弯曲度曲线 3、0.85弯曲度曲线 4、0.1度弯曲曲线 5、综合对比 总结 前言 在很多的关于路线的gis应用中,我们…

开源项目ChatGPT-Next-Web的容器化部署(三)-- k8s deployment.yaml部署

一、说在前面的话 有了docker镜像,要把一个项目部署到K8S里,主要就是编写deployment.yaml。 你需要考虑的是: 环境变量服务的健康检测持久化启动命令程序使用的数据源程序使用的配置文件 因为本前端项目比较简单,这里只做一个…

网络工程师笔记15(OSPF协议-2)

OSPF协议 OSPF是典型的链路状态路由协议,是目前业内使用非常广泛的 IGP 协议之一。 Router-ID(Router ldentifier,路由器标识符),用于在一个 OSPF 域中唯一地标识一台路由器。Router-ID 的设定可以通过手工配置的方式,或使用系统自…

RuoYi 自定义字典列表页面编码翻译

“字典数据”单独维护,而不是使用系统自带的字典表,应该如何使用这样的字典信息呢? 系统字典的使用,请参考: 《RuoYi列表页面字典翻译的实现》 https://blog.csdn.net/lxyoucan/article/details/136877238 需求说明…

IPC网络摄像头媒体视屏流MI_VIF结构体

一个典型的IPC数据流 下图是一个典型的IPC数据流模型,流动过程如下: 1. 建立Vif->Vpe->Venc的绑定关系; 2. Sensor 将数据送入vif处理; 3. Vif 将处理后的数据写入Output Port申请的内存,送入下一级;…

CI/CD环境搭建

服务简介 Gitlab 官网:https://about.gitlab.com/ GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的Web服务。安装方法是参考GitLab在GitHub上的Wiki页面。Gitlab是被广泛使用的基于git的开源代码管…