设计模式篇(Java):前言(UML类图、七大原则)

news2025/5/22 21:18:54

编写软件过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让程序(软件),具有更好:

  • 代码重用性 (即:相同功能的代码,不用多次编写)
  • 可读性 (即:编程规范性, 便于其他程序员的阅读和理解)
  • 可扩展性 (即:当需要增加新的功能时,非常的方便,称为可维护)
  • 可靠性 (即:当我们增加新的功能后,对原来的功能没有影响)
  • 使程序呈现高内聚,低耦合的特性

一、七大原则

设计模式原则,其实就是程序员在编程时,应当遵守的原则,也是各种设计模式的基础

1.1 单一职责原则

概述

一个类应该只负责一项职责。如果一个类负责两个职责,那么修改其中一个职责的功能时,可能会影响另一个职责。

示例

方案一:

/**
 * 示例单一原则
 * @author cVzhanshi
 * @create 2023-01-29 20:23
 */
public class single {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        vehicle.run("摩托车");
        vehicle.run("轮船");
        vehicle.run("飞机");
    }
}


class Vehicle{
    public void run (String vehicle){
        System.out.println(vehicle + "在公路上走...");
    }
}

// 运行结果
// 摩托车在公路上走...
// 轮船在公路上走...
// 飞机在公路上走...

分析:

  1. 在示例一的 run 方法中,违反了单一职责原则
  2. 解决的方案非常的简单,根据交通工具运行方法不同,分解成不同类即可

方案二:

class RoadVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + "公路运行");
    }
}
class AirVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + "天空运行");
    }
}

class WaterVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + "水中运行");
    }
}

分析:

  1. 遵守单一职责原则
  2. 改动很大,即将类分解,同时修改客户端
  3. 改进:直接修改 Vehicle 类,改动的代码会比较少

方案三:

class Vehicle2 {
    public void run(String vehicle) {
        //处理
        System.out.println(vehicle + " 在公路上运行....");
    }
    public void runAir(String vehicle) {
        System.out.println(vehicle + " 在天空上运行....");
    }
    public void runWater(String vehicle) {
        System.out.println(vehicle + " 在水中行....");
    }
}

分析:

  1. 这种修改方法没有对原来的类做大的修改,只是增加方法
  2. 这里虽然没有在类这个级别上遵守单一职责原则,但是在方法级别上,仍然是遵守单一职责

单一职责原则注意事项和细节

  • 降低类的复杂度,一个类只负责一项职责。
  • 提高类的可读性,可维护性
  • 降低变更引起的风险
  • 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责原则(如上述的方案三,如果方案三还有其他的方法,那么就违反了单一职责原则)

1.2 接口隔离原则

概述

客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上

示例

说明:

  • 接口A中有五个方法
  • 类D依赖类B使用到了接口中的1,2,3方法
  • 类E依赖类C使用到了接口中的1,4,5方法
/**接口隔离原则示例
 * @author cVzhanshi
 * @create 2023-01-30 15:44
 */
public class demo01 {
    public static void main(String[] args) {
        B b = new B();
        D d = new D();
        d.depend1(b);
        d.depend2(b);
        d.depend3(b);

        C c = new C();
        E e = new E();
        e.depend1(c);
        e.depend4(c);
        e.depend5(c);

    }
}

class D{
    public void depend1(A a){
        a.function1();
    }
    public void depend2(A a){
        a.function2();
    }
    public void depend3(A a){
        a.function3();
    }
}

class E{
    public void depend1(A a){
        a.function1();
    }
    public void depend4(A a){
        a.function4();
    }
    public void depend5(A a){
        a.function5();
    }
}


class C implements A{
    @Override
    public void function1() {
        System.out.println("C 实现了 function1");
    }

    @Override
    public void function2() {
        System.out.println("C 实现了 function2");
    }

    @Override
    public void function3() {
        System.out.println("C 实现了 function3");
    }

    @Override
    public void function4() {
        System.out.println("C 实现了 function4");
    }

    @Override
    public void function5() {
        System.out.println("C 实现了 function5");
    }
}


class B implements A{

    @Override
    public void function1() {
        System.out.println("B 实现了 function1");
    }

    @Override
    public void function2() {
        System.out.println("B 实现了 function2");
    }

    @Override
    public void function3() {
        System.out.println("B 实现了 function3");
    }

    @Override
    public void function4() {
        System.out.println("B 实现了 function4");
    }

    @Override
    public void function5() {
        System.out.println("B 实现了 function5");
    }
}

interface A{
    void function1();
    void function2();
    void function3();
    void function4();
    void function5();
}

分析:

  • 如果接口A对于类D和类E来说不是最小接口,那么类 B 和类 C 必须去实现他们不需要的方法。所以违反了接口隔离原则

  • 改进:将接口A拆分为独立的几个接口,类 D 和类E 分别与他们需要的接口建立依赖关系。采用接口隔离原则

  • 拆分详情:

    • 接口A存在方法1,因为类D,E都使用了
    • 接口B存在方法2,3,因为类D单独使用了
    • 接口C存在方法4,5,因为类E单独使用了

    这样的话类D、E依赖的类就不需要实现他们不需要的方法了

示例代码

/**
 * 接口隔离原则示例
 * @author cVzhanshi
 * @create 2023-01-30 15:57
 */
public class demo02 {
    public static void main(String[] args) {
        D d = new D();
        E e = new E();
        F f = new F();
        G g = new G();
        
        d.depend1(f);
        d.depend2(f);
        d.depend3(f);
        
        e.depend1(g);
        e.depend4(g);
        e.depend5(g);
    }
}

class D{
    public void depend1(F f){
        f.function1();
    }

    public void depend2(F f){
        f.function2();
    }

    public void depend3(F f){
        f.function3();
    }
}

class E{
    public void depend1(G g){
        g.function1();
    }

    public void depend4(G g){
        g.function4();
    }

    public void depend5(G g){
        g.function5();
    }
}

// 依赖类
class F implements A, B{

    @Override
    public void function1() {
        System.out.println("F 实现了 function1");
    }

    @Override
    public void function2() {
        System.out.println("F 实现了 function2");
    }

    @Override
    public void function3() {
        System.out.println("F 实现了 function3");
    }
}

// 依赖类
class G implements A, C{

    @Override
    public void function1() {
        System.out.println("G 实现了 function1");
    }

    @Override
    public void function4() {
        System.out.println("G 实现了 function4");
    }

    @Override
    public void function5() {
        System.out.println("G 实现了 function5");
    }
}

interface A{
    void function1();
}

interface B{
    void function2();
    void function3();
}

interface C{
    void function4();
    void function5();
}

1.3 依赖倒转原则

概述

  • 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  • 抽象不应该依赖细节,细节应该依赖抽象
  • 依赖倒转(倒置)的中心思想是面向接口编程
  • 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在 java 中,抽象指的是接口或抽象类,细节就是具体的实现类
  • 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给实现类去完成

示例

示例一:

/**
 * 依赖倒转原则示例
 * @author cVzhanshi
 * @create 2023-01-30 20:24
 */
public class demo01 {
    public static void main(String[] args) {
        Person person = new Person();
        person.receive(new Email());
    }
}

class Email{
    public String getInfo(){
        return "电子邮箱信息:hello";
    }
}


class Person{
    public void receive(Email email){
        System.out.println(email.getInfo());
    }
}

分析:

  1. 如果我们要获取微信,短信等等的信息,则需要新增类,同时 Perons 也要增加相应的接收方法
  2. 改进:引入一个抽象的接口 IReceiver, 表示接收者, 这样 Person 类与接口 IReceiver 发生依赖。Email, WeiXin 等等属于接收的范围,他们各自实现 IReceiver 接口就可以了,这样客户端不需要改变。这样我们就符合依赖倒转原则

示例二:

/**
 * @author cVzhanshi
 * @create 2023-01-30 20:31
 */
public class demo02 {
    public static void main(String[] args) {
        Person person = new Person();
        person.receive(new WeChat());
        person.receive(new Email());
    }
}

interface IReceive{
    String getInfo();
}

class Email implements IReceive{
    @Override
    public String getInfo() {
        return "电子邮箱信息:hello";
    }
}

class WeChat implements IReceive{
    @Override
    public String getInfo() {
        return "微信信息:weChat";
    }
}

class Person{
    public void receive(IReceive receive){
        System.out.println(receive.getInfo());
    }
}

依赖关系传递的三种方式

接口传递

/**
 * @author cVzhanshi
 * @create 2023-01-30 20:31
 */
public class demo02 {
    public static void main(String[] args) {
        Person person = new Person();
        person.receive(new WeChat());
        person.receive(new Email());
    }
}

interface IReceive{
    String getInfo();
}

class Email implements IReceive{
    @Override
    public String getInfo() {
        return "电子邮箱信息:hello";
    }
}

class WeChat implements IReceive{
    @Override
    public String getInfo() {
        return "微信信息:weChat";
    }
}

class Person{
    public void receive(IReceive receive){
        System.out.println(receive.getInfo());
    }
}

构造方法传递

/**
 * @author cVzhanshi
 * @create 2023-01-30 20:31
 */
public class demo02 {
    public static void main(String[] args) {
        EmailClass emailClass = new EmailClass();
        Person person = new Person(emailClass);
        person.getInfo();

    }
}

interface IReceive{
    void getInfo();
}

interface Email{
    public void getMessage();
}

class EmailClass implements Email{

    @Override
    public void getMessage() {
        System.out.println("EmailClass messages");
    }
}

class Person implements IReceive{
    private Email email;

    public Person(Email email) {
        this.email = email;
    }

    @Override
    public void getInfo() {
        email.getMessage();
    }
}

通过setter方法传递

/**
 * @author cVzhanshi
 * @create 2023-01-30 20:31
 */
public class demo02 {
    public static void main(String[] args) {
        EmailClass emailClass = new EmailClass();
        Person person = new Person();
        person.setEmail(emailClass);
        person.getInfo();

    }
}

interface IReceive{
    void getInfo();
}

interface Email{
    public void getMessage();
}

class EmailClass implements Email{

    @Override
    public void getMessage() {
        System.out.println("EmailClass messages");
    }
}

class Person implements IReceive{
    private Email email;

    public void setEmail(Email email) {
        this.email = email;
    }

    @Override
    public void getInfo() {
        email.getMessage();
    }
}

依赖倒转原则的注意事项和细节

  • 低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好
  • 变量的声明类型尽量是抽象类或接口, 这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化
  • 继承时遵循里氏替换原则

1.4 里氏替换原则

概述

继承在给程序设计带来便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承, 则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子 类的功能都有可能产生故障。

里氏替换原则

  • 所有引用基类的地方必须能透明地使用其子类的对象

  • 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法

  • 继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖来解决问题

就是说,使用继承不要去破坏原有的东西,不要给程序带来侵入性。

示例

示例一:

public class demo01 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println("11-3=" + a.func1(11, 3));  // 11-3=8
        System.out.println("1-8=" + a.func1(1, 8));    // 1-8=-7
        System.out.println("-----------------------");
        B b = new B();
        System.out.println("11-3=" + b.func1(11, 3));   // 11-3=14    
        System.out.println("1-8=" + b.func1(1, 8));     // 1-8=9
        System.out.println("11+3+9=" + b.func2(11, 3)); // 11+3+9=23
    }
}

class A {
    public int func1(int num1, int num2) {
        return num1 - num2;
    }
}


class B extends A {
    public int func1(int a, int b) {
        return a + b;
    }

    public int func2(int a, int b) {
        return func1(a, b) + 9;
    }
}

说明:因为类B不知情的情况下重写了类A的方法,把类A 的减法变成加法。导致了main函数类B想使用减法是出错。这就是继承带来的侵入性。

改造:原来的父类和子类都继承一个更通俗的基类,原有的继承关系去掉, 采用依赖,聚合,组合等关系代替.

public class demo02 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println("11-3=" + a.func1(11, 3));  // 11-3=8
        System.out.println("1-8=" + a.func1(1, 8));    // 1-8=-7
        System.out.println("-----------------------");
        B b = new B();
        System.out.println("11-3=" + b.func3(11, 3));   // 11-3=8
        System.out.println("1-8=" + b.func3(1, 8));     // 1-8=-7
        System.out.println("11+3+9=" + b.func2(11, 3)); // 11+3+9=23
    }
}

class Base {

}
class A extends Base {
    public int func1(int num1, int num2) {
        return num1 - num2;
    }
}


class B extends Base {
    private A a = new A();
    public int func1(int a, int b) {
        return a + b;
    }

    public int func2(int a, int b) {
        return func1(a, b) + 9;
    }

    public int func3(int a, int b) {
        return this.a.func1(a, b);
    }
}

1.5 开闭原则

概述

  • 模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。
  • 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已 有的代码来实现变化

示例

代码示例一:

public class demo01 {
    public static void main(String[] args) {
        GraphicEditor graphicEditor = new GraphicEditor();
        graphicEditor.drawShape(new Rectangle());
        graphicEditor.drawShape(new Circle());
    }
}

// 使用方  这是一个用于绘图的类
class GraphicEditor {
    public void drawShape(Shape s) {
        if (s.m_type == 1)
            drawRectangle(s);
        else if (s.m_type == 2)
            drawCircle(s);
    }

    public void drawRectangle(Shape r) {
        System.out.println("矩形");
    }

    public void drawCircle(Shape r) {
        System.out.println("圆形");
    }
}

class Shape {
    int m_type;
}

class Rectangle extends Shape {
    Rectangle() {
        super.m_type = 1;
    }
}

class Circle extends Shape {
    Circle() {
        super.m_type = 2;
    }
}

说明:

  • 优点是比较好理解,简单易操作。
  • 缺点是违反了设计模式的ocp原则,即对扩展开放(提供方),对修改关闭(使用方)。 即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码.
  • 比如我们这时要新增加一个图形种类 三角形,我们需要做如下修改,修改的地方 较多

修改:思路:把创建Shape类做成抽象类,并提供一个抽象的draw方法,让子类去实现即可, 这样我们有新的图形种类时,只需要让新的图形类继承Shape,并实现draw方法即可, 使用方的代码就不需要修 -> 满足了开闭原则

/**
 * @author cVzhanshi
 * @create 2023-03-14 10:12
 */
public class demo02 {
    public static void main(String[] args) {
        Editor editor = new Editor();

        editor.drawShape(new A());
        editor.drawShape(new B());
    }
}

class Editor{
    public void drawShape(Shape s){
        s.draw();
    }
}
abstract class Shape{
    public abstract void draw();
}

class A extends Shape {
    @Override
    public void draw() {
        System.out.println("画A");
    }
}

class B extends Shape {
    @Override
    public void draw() {
        System.out.println("画B");
    }
}

1.6 迪米特法则

概述

  • 一个对象应该对其他对象保持最少的了解
  • 类与类关系越密切,耦合度越大
  • 迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public 方法,不对外泄露任何信息。
  • 迪米特法则还有个更简单的定义:只与直接的朋友通信

直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系, 我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部

示例

错误示例,违背了迪米特法则

class Test {
    public void test() {
        System.out.println("测试");
    }
}


class Apple {
    public void test() {
        // 陌生的类最好不要以局部变量的形式出现在类的内部
        Test test = new Test();
        test.test();
    }
}

改正

class Test {
    public void test() {
        System.out.println("测试");
    }
}


class Apple {
    public void test(Test test) {
        test.test();
    }
}

迪米特法则注意事项和细节

  • 迪米特法则的核心是降低类之间的耦合。
  • 但是注意:由于每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类间(对象间)耦合关系, 并不是要求完全没有依赖关系。

1.7 合成复用原则

尽量使用合成或者聚合 的方式,而不是使用聚合

1.8 设计原则核心思想

  • 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
  • 针对接口编程,而不是针对实现编程。
  • 为了交互对象之间的松耦合设计而努力

二、UML类图

用于描述系统中的类(对象)本身的组成和类(对象)之间的各种静态关系

类之间的关系:依赖、泛化(继承)、实现、关联、聚合与组合

  • :类图分三层,第一层是类名,如果是抽象类就用斜体表示;第二层代表属性或字段;第三层是类的操作即方法,方法前面会用符号表示权限修饰符,‘+’表示public,‘-’表示private,‘#’表示protected。

    在这里插入图片描述

  • 接口:接口和类图的区别是顶端有<<interface>>显示,第二行表示的是接口的方法;接口还有第二种表示方法(棒棒糖表示法),圆圈边上表示接口名称,接口的方法再实现类里面。

    在这里插入图片描述

  • 继承关系空心三角形 + 实线

    在这里插入图片描述

  • 实现关系空心三角形 + 虚线

    在这里插入图片描述

  • 关联关系实线 + 箭头

    在这里插入图片描述

  • 聚合关系:空心的菱形 + 实现箭头;聚合表示一种弱的”拥有“关系,体现的是A对象可以包含B对象,但B对象不是A对象一部分

    空心菱形 + 实线箭头表示

    在这里插入图片描述

  • 组合(合成)关系:组成是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。组合关系(关联关系和聚合关系也可以有基数)还具备基数的,表示对应关系。

    实心的菱形 + 实线箭头

    在这里插入图片描述

  • 依赖关系虚线 + 箭头

    如:类中用到了对方、成员属性、方法的返回类型、方法接收的参数类型、方法中使用到

    在这里插入图片描述

    在这里插入图片描述

三、设计模式简介

  • 设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验, 模式不是代码,而是某类问题的通用解决方案,设计模式(Design pattern) 代表了最佳的实践。
  • 设计模式的本质提高软件的维护性,通用性和扩展性,并降低软件的复杂度。

设计模式分为三种类型,共23种

  • 创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式
  • 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
  • 行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模 式、策略模式、职责链模式(责任链模式)。

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

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

相关文章

Web自动化测试平台的设计与落地

目录 前言 一、目标和定位 二、平台特点 三、系统架构 四、相关技术栈 五、UI概览 六、待完善部分 总结&#xff1a; 前言 我最初开始接触Web自动化测试的时候&#xff0c;没有直接的领路人&#xff0c;测试行业知识也远不及如今这么丰富和易获取&#xff0c;当时我对于…

Hello算法学习笔记之搜索

一、二分查找 1.从数组中找到target的索引 注意&#xff1a;while条件是< O&#xff08;logn&#xff09; 二分查找并非适用于所有情况&#xff0c;原因如下&#xff1a; 二分查找仅适用于有序数据。若输入数据无序&#xff0c;为了使用二分查找而专门进行排序&#xff…

视频处理器对LED显示屏的作用

视频处理器在LED显示屏中扮演着重要的角色&#xff0c;其作用如下&#xff1a; 图像和视频信号处理&#xff1a;视频处理器负责对输入的图像和视频信号进行处理和优化&#xff0c;以确保在LED显示屏上呈现出高质量的图像和视频内容。它可以对图像进行去噪、锐化、色彩校正、亮度…

【数据结构】复杂度

目录 &#x1f4d6;什么是数据结构&#xff1f;&#x1f4d6;什么是算法&#xff1f;&#x1f4d6;算法效率&#x1f4d6;时间复杂度&#x1f516;大O的渐进表示法&#x1f516;常见时间复杂度计算举例&#x1f516;面试题&#xff1a;消失的数字 &#x1f4d6;空间复杂度&…

I2C协议应用(嵌入式学习)

I2C协议&应用 0. 前言1. 概念2. 特点&工作原理3. 应用示例代码模板HAL模板 0. 前言 I2C是Inter-Integrated Circuit的缩写&#xff0c;它是一种广泛使用的串行通信协议。它由飞利浦&#xff08;现在是NXP Semiconductors&#xff09;开发&#xff0c;并已成为各种电子…

无迹卡尔曼滤波在目标跟踪中的作用(一)

在前一节中&#xff0c;我们介绍了扩展卡尔曼滤波算法EKF在目标跟踪中的应用&#xff0c;其原理是 将非线性函数局部线性化&#xff0c;舍弃高阶泰勒项&#xff0c;只保留一次项 &#xff0c;这就不可避免地会影响结果的准确性&#xff0c;除此以外&#xff0c;实际中要计算雅各…

软件测试面试试卷,答对90%直接入职大厂

一&#xff0e;填空 1、 系统测试使用&#xff08; C &#xff09;技术, 主要测试被测应用的高级互操作性需求, 而无需考虑被测试应用的内部结构。 A、 单元测试 B、 集成测试 C、 黑盒测试 D、白盒测试 2、单元测试主要的测试技术不包括&#xff08;B &…

Linux 如何刷新 DNS 缓存

Linux 如何刷新 DNS 缓存 全文&#xff1a;如何刷新 DNS 缓存 (macOS, Linux, Windows) Unix Linux Windows 如何刷新 DNS 缓存 (macOS, FreeBSD, RHEL, CentOS, Debian, Ubuntu, Windows) 请访问原文链接&#xff1a;https://sysin.org/blog/how-to-flush-dns-cache/&#…

Elasticsearch:install

ElasticSearch Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。 Elasticsearch结合Kibana、Logstash、Beats&#xff0c;也就是elastic stack(ELK)。被广泛应用在日志分析、实时监控&#xff08;CPU、Memory、Program&#xff09;等领域。 elasticsearch是…

【Linux 驱动篇(一)】字符设备驱动开发

文章目录 一、字符设备驱动简介二、字符设备驱动开发步骤1. 驱动模块的加载和卸载2. 字符设备注册与注销3. 实现设备的具体操作函数3.1 能够对 chrtest 进行打开和关闭操作3.2 对 chrtest 进行读写操作 4. 添加 LICENSE 和作者信息 三、Linux 设备号1. 设备号的组成 一、字符设…

网工内推 | 2023应届生专场,上市公司招网工,CCNP以上认证优先

01 浙江宇视科技有限公司 招聘岗位&#xff1a;IT网络工程师 职责描述&#xff1a; 1、负责公司内部核心网络建设&#xff0c;进行网络架构的规划、设计、调整、性能优化&#xff1b; 2、负责公司网络环境的管理&#xff0c;配置&#xff0c;监控、排错&#xff0c;维护&#…

津津乐道设计模式 - 适配器模式详解(家里电器电源标准不统一的问题都解决了)

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Micro麦可乐的博客 &#x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程&#xff0c;入门到实战 &#x1f33a;《RabbitMQ》…

Servlet 相关内容

1. Servlet 1.1 Servlet概述 Servlet 是 SUN 公司提供的一套规范&#xff0c;名称就叫 Servlet 规范&#xff0c;它也是 JavaEE 规范之一&#xff0c;可以通过API来学习。目前在Oracle官网中的最新版本是JavaEE8&#xff0c;该网址中介绍了JavaEE8的一些新特性。当然&#xff…

【C语言初阶】带你轻松玩转所有常用操作符(2) ——赋值操作符,单目操作符

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 Hello,这里是君兮_&#xff0c;今天给大家带来的是有关操作符的第二部分内容&#xff0c;废话不多说&#xff0c;咱们直接开始吧&#xff01; 在正式开始之前&#xff0c;我们还是借助一张思维导图帮助大致简单回忆一下有…

Docker-compose的使用

目录 Docker-compose 简介 docker-compose的安装 docker-compose.yaml文件说明 compose的常用命令 总结 Docker-compose 简介 Docker-compose 是用于定义和运行多容器的 Docker 应用程序的工具。可以使用YAML文件来配置应用程序的服务。&#xff08;通俗讲是可以通过yml文…

LeetCode108-将有序数组转换为二叉搜索树

题目来源 108. 将有序数组转换为二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 题目 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵高度平衡 二叉搜索树。 高度平衡二叉树是一棵满足「每个节点的左右两个子树的高度差的…

智慧地下采矿,“像素游戏”智能呈现

在这个像素世界里&#xff0c;我们需要一个智能地下采矿可视化综合管理平台&#xff0c;来帮助我们管理和监控地下采矿全流程。 图扑软件依托自主研发的 HT for Web 产品&#xff0c;结合三维定制化渲染、动态模拟、物理碰撞、5G、物联网、云计算及大数据等先进技术&#xff0c…

从零开始理解Linux中断架构(8)---执行上下文之CPU上下文

1 CPU上下文的来由 CPU上下文是切换任务到CPU时需要保存和恢复的CPU寄存器。ARM64需要保存的寄存器如下图所示 X19-X29作为CPU上下文的依据是什么? 实际上这里使用了一个隐含的事实:Linux所有的任务切换都是在内核中__switch_to函数中进行的,当前任务通过__…

KubeSphere 社区双周报 | OpenFunction 发布 v1.1.1 | 2023.6.9-6.22

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者&#xff0c;并对近期重要的 PR 进行解析&#xff0c;同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为&#xff1a;2023.6.9-6.22。 …

Elisp之定时器run-with-timer、run-with-idle-timer、run-at-time 区别(二十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…