创建型设计模式04-建造者模式

news2024/12/31 4:21:37

✨作者:猫十二懿

❤️‍🔥账号:CSDN 、掘金 、个人博客 、Github

🎉公众号:猫十二懿

建造者模式

1、建造者模式介绍

建造者模式是一种创建型设计模式,用于将一个复杂对象的构造过程与其表示分离开来,使得同样的构造过程可以创建不同的表示。该模式通过建造者类和指导者类的协作,将复杂的构造过程简化,并且增加了灵活性和可维护性。

1.1 建造者模式结构图

image-20230425222057889

  1. Builder:是为创建一个Product对象的各个部件指定的抽象接口
  2. ConcreteBuilder:是具体建造者,实现Builder接口,构造和装配各个部件。(实现具体的构建过程)
  3. Product:产品角色。
  4. Director:指挥者(指导者),是构建一个使用Builder接口的对象。

1.2 建造者模式基本代码

Product类:

/**
 * @author Shier
 * CreateTime 2023/4/25 22:26
 * 产品类
 */
public class Product {
    ArrayList<String>  parts = new ArrayList<>();

    /**
     * 添加新的产品部件
     * @param part
     */
    public void add(String part){
        parts.add(part);
    }

    /**
     * 列举所有的产品
     */
    public void show(){
        for (String part : parts) {
            System.out.println(part);
        }
    }
}

Builder 类

/**
 * @author Shier
 * CreateTime 2023/4/25 22:30
 * 抽象建造者类
 */
public abstract class Builder {
    /**
     * 建造部件A
     */
    public abstract void buildPartA();

    /**
     * 建造部件B
     */
    public abstract void buildPartB();

    /**
     * 获得产品建造后返回结果
     * @return
     */
    public abstract Product getResult(); 
}

ConcreteBuilderA 类:

/**
 * @author Shier
 * CreateTime 2023/4/25 22:33
 * 具体建造者A
 */
public class ConcreteBuilderA extends Builder{

    private Product product  =new Product();

    @Override
    public void buildPartA() {
        System.out.println("部件A");
    }

    @Override
    public void buildPartB() {
        System.out.println("部件B");
    }

    @Override
    public Product getResult() {
        return product;
    }
}

ConcreteBuilderB类与ConcreteBuilderA 类一样的,只是B的产品是C和D,不在重复写。

Director类:

/**
 * @author Shier
 * CreateTime 2023/4/25 22:36
 * 指导者类
 */
public class Director {
    public void construct(Builder builder){
        builder.buildPartA();
        builder.buildPartB();
    }
}

客户端类:

/**
 * @author Shier
 * CreateTime 2023/4/25 22:37
 * 客户端代码
 */
public class Client {
    public static void main(String[] args) {
        Director director = new Director();
        ConcreteBuilderA builderA = new ConcreteBuilderA();
        ConcreteBuilderB builderB = new ConcreteBuilderB();
        // 指导者用ConcreteBuilderA创建方法来建造产品
        director.construct(builderA); // A建造者创建的产品是A和B
        Product resultA = builderA.getResult();
        resultA.show();

        // 指导者用ConcreteBuilderB创建方法来建造产品
        director.construct(builderB);// B建造者创建的产品是C和D
        Product resultB = builderB.getResult();
        resultB.show();
    }
}

建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用的模式。

2、具体案例

画小人,要求是小人要有头、身体、两手、两脚就可以了。

2.1 不使用建造者模式-画小人

/**
 * @author Shier
 * CreateTime 2023/4/25 22:45
 */
public class Test extends JFrame {
    public Test() {
        setSize(400, 400);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public void paint(Graphics graphics) {
        //瘦小人
        graphics.drawOval(150, 120, 30, 30);   //头
        graphics.drawRect(160, 150, 10, 50);   //身体
        graphics.drawLine(160, 150, 140, 200); //左手
        graphics.drawLine(170, 150, 190, 200); //右手
        graphics.drawLine(160, 200, 145, 250); //左脚
        graphics.drawLine(170, 200, 185, 250); //右脚

        胖小人
        //graphics.drawOval(250, 120, 30, 30);   //头
        //graphics.drawOval(245, 150, 40, 50);   //身体
        //graphics.drawLine(250, 150, 230, 200); //左手
        //graphics.drawLine(280, 150, 300, 200); //右手
        //graphics.drawLine(260, 200, 245, 250); //左脚
        //graphics.drawLine(270, 200, 285, 250); //右脚
    }

    public static void main(String[] args) {
        new Test();
    }
}

如果在画一个胖小人,就是取消注释就可,但是有没有可能你复制别人的或者自己写的时候会漏写了代码,就有可能出现小人是缺胳膊少腿的情况。

就算将瘦小人和胖小人分别单独为一个类,但是这样还是避免不了缺胳膊少腿的情况呀。

所以说可以直接使用建造者模式,将两者普通同的部分抽取到抽象类当中

2.2 使用建造者模式-画小人

建造小人抽象类:

/**
 * @author Shier
 * CreateTime 2023/4/25 23:01
 * 建造小人抽象类
 */
public abstract class PersonBuilder {
    protected Graphics graphics;

    public PersonBuilder(Graphics graphics) {
        this.graphics = graphics;
    }
    // 头
    public abstract  void buildHead();
    // 身体
    public abstract  void buildBody();
    // 左手
    public abstract  void buildArmLeft();
    // 右手
    public abstract  void buildArmRight();
    // 右腿
    public abstract  void buildLegRight();
    // 左腿
    public abstract  void buildLegLeft();
}

胖小人类:

/**
 * @author Shier
 * CreateTime 2023/4/25 22:53
 * 胖小人
 */
public class PersonFatBuilder extends PersonBuilder {
    public PersonFatBuilder(Graphics graphics) {
        super(graphics);
    }

    /**
     * 头
     */
    @Override
    public void buildHead() {
        graphics.drawOval(250, 120, 30, 30);
    }

    /**
     * 身体
     */
    @Override
    public void buildBody() {
        graphics.drawOval(245, 150, 40, 50);
    }

    /**
     * 左手
     */
    @Override
    public void buildArmLeft() {
        graphics.drawLine(250, 150, 230, 200);
    }

    /**
     * 右手
     */
    @Override
    public void buildArmRight() {
        graphics.drawLine(280, 150, 300, 200);
    }

    /**
     * 右腿
     */
    @Override
    public void buildLegRight() {
        graphics.drawLine(270, 200, 285, 250);
    }

    /**
     * 左腿
     */
    @Override
    public void buildLegLeft() {
        graphics.drawLine(260, 200, 245, 250);
    }
}

瘦小人类:

/**
 * @author Shier
 * CreateTime 2023/4/25 22:53
 * 瘦小人
 */
public class PersonThinBuilder extends PersonBuilder {
    public PersonThinBuilder(Graphics graphics) {
        super(graphics);
    }

    /**
     * 头
     */
    @Override
    public void buildHead() {
        graphics.drawOval(150, 120, 30, 30);
    }

    /**
     * 身体
     */
    @Override
    public void buildBody() {
        graphics.drawRect(160, 150, 10, 50);
    }

    /**
     * 左手
     */
    @Override
    public void buildArmLeft() {
        graphics.drawLine(160, 150, 140, 200);
    }

    /**
     * 右手
     */
    @Override
    public void buildArmRight() {
        graphics.drawLine(170, 150, 190, 200);
    }

    /**
     * 右腿
     */
    @Override
    public void buildLegRight() {
        graphics.drawLine(170, 200, 185, 250);
    }

    /**
     * 左腿
     */
    @Override
    public void buildLegLeft() {
        graphics.drawLine(160, 200, 145, 250);
    }
}

建造人指挥类-指导建造怎么样的小人

指挥者(Director),用它来控制建造过程,也用它来隔离用户与建造过程的关联

/**
 * @author Shier
 * CreateTime 2023/4/25 23:08
 */
public class PersonDirector {
    private PersonBuilder personBuilder;

    /**
     * 初始化时指定要画什么样的人
     * @param personBuilder
     */
    public PersonDirector(PersonBuilder personBuilder) {
        this.personBuilder = personBuilder;
    }
    public void CreatePerson(){
        personBuilder.buildHead();
        personBuilder.buildBody();
        personBuilder.buildArmLeft();
        personBuilder.buildArmRight();
        personBuilder.buildLegRight();
        personBuilder.buildLegLeft();
    }
}

测试类:

/**
 * @author Shier
 * CreateTime 2023/4/25 22:45
 */
public class Test extends JFrame {
    public Test() {
        setSize(400, 400);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public void paint(Graphics graphics) {
        // 建造瘦小人
        PersonBuilder thinBuilder = new PersonThinBuilder(graphics);
        PersonDirector thinDirector = new PersonDirector(thinBuilder);
        thinDirector.CreatePerson();
        // 建造胖小人
        PersonFatBuilder fatBuilder = new PersonFatBuilder(graphics);
        PersonDirector fatDirector = new PersonDirector(fatBuilder);
        fatDirector.CreatePerson();
    }

    public static void main(String[] args) {
        new Test();
    }
}

在抽象类中创建了普遍存在的功能,只要继承抽象类就可实现复杂的构建过程,复杂构建过程的实现都在PersonBuilderA/B中实现了,表示在指挥者类实现

如果还有新的需求就是直接继承PersonBuilder类,让客户端调用实现即可。但是如果我要画人的五官,手指等人的细节的地方,又该如何实现?

如果这些细节是每个具体的小人都需要构建的,那就应该要加进去,反之就没必要。其实建造者模式是逐步建造产品的,所以建造者的Builder类里的那些建造方法必须要足够普遍,以便为各种类型的具体建造者构造。

2.3 电脑组件案例(简易完整版建造者模式)

我们要生产一台电脑,它具有CPU、显卡、内存等组件,每个组件都有不同的品牌、型号、参数等属性。我们可以使用建造者模式来实现其构建:

  1. 首先,需要定义电脑类Computer,它具有CPU、显卡、内存等组件属性;
  2. 然后,定义ComputerBuilder抽象类,其中包含设置CPU、设置显卡、设置内存等抽象方法,用于实现电脑组装过程的各个步骤;
  3. 接着,定义具体的电脑建造者类A、B、C等,分别实现ComputerBuilder中的抽象方法,构建不同的电脑配置;
  4. 最后,定义Director类,该类包含了构建电脑的方法buildComputer,其中封装了调用ComputerBuilder中各个步骤的顺序和逻辑,通过注入不同的具体建造者类,可以构建出不同的电脑对象。

这样,使用建造者模式可以将电脑的构建逻辑封装在具体建造者中,客户端代码仅需通过Director调用buildComputer方法来指定需要的电脑构建方式,从而实现了将复杂对象的构建与表示分离。它可以将对象的构建过程抽象化,使得相同的构建过程可以创建不同的表示。相比于直接在构造函数中设置可选参数,建造者模式使用setter的方式进行初始化,非常的灵活

那么看懂的要求,再来看看具体的代码实现吧

Computer类:也就是上面建造者模式的Product类

/**
 * @author Shier
 * CreateTime 2023/4/26 22:01
 */
public class Computer {
    private String cpu;
    private String gpu;
    private String  memory;

    public void setGpu(String gpu) {
        this.gpu = gpu;
    }

    public void setMemory(String  memory) {
        this.memory = memory;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    @Override
    public String toString() {
        return "Computer:{" +
                "cpu='" + cpu + '\'' +
                ", gpu='" + gpu + '\'' +
                ", memory=" + memory +
                '}';
    }
}

ComputerBuilder类:

/**
 * @author Shier
 * CreateTime 2023/4/26 22:02
 * ComputerBuilder抽象类
 */
public abstract class ComputerBuilder {
    protected Computer computer;

    public Computer getComputer() {
        return computer;
    }

    /**
     * 构建Computer类
     */
    public void createNewComputer(){
        computer = new Computer();
    }
    public abstract void buildCpu();

    public abstract void buildGpu();

    public abstract void buildMemory();
}

三个具体的建造者类:每一个都实现ComputerBuilder中的方法,并定义自己的电脑配置

ComputerBuilderA:

/**
 * @author Shier
 * CreateTime 2023/4/26 22:05
 * ComputerBuilderA 具体建造者
 */
public class ComputerBuilderA extends ComputerBuilder{
    @Override
    public void buildCpu() {
        computer.setCpu("Intel i7-12500H");
    }

    @Override
    public void buildGpu() {
        computer.setGpu("NVIDIA GeForce RTX 1650");
    }

    @Override
    public void buildMemory() {
        computer.setMemory("16G");
    }
}

ComputerBuilderB:

/**
 * @author Shier
 * CreateTime 2023/4/26 22:05
 * ComputerBuilderB 具体建造者
 */
public class ComputerBuilderB extends ComputerBuilder{
    @Override
    public void buildCpu() {
        computer.setCpu("Intel i9 4090X");
    }

    @Override
    public void buildGpu() {
        computer.setGpu("NVIDIA GeForce RTX 4090");
    }

    @Override
    public void buildMemory() {
        computer.setMemory("64G");
    }
}

ComputerBuilderC:

/**
 * @author Shier
 * CreateTime 2023/4/26 22:05
 * ComputerBuilderC 具体建造者
 */
public class ComputerBuilderC extends ComputerBuilder{
    @Override
    public void buildCpu() {
        computer.setCpu("AMD Ryzen 9 5900X");
    }

    @Override
    public void buildGpu() {
        computer.setGpu("NVIDIA GeForce RTX 3080");
    }

    @Override
    public void buildMemory() {
        computer.setMemory("24G");
    }
}

Director类:

/**
 * @author Shier
 * CreateTime 2023/4/26 22:10
 * 创建Director类,用于指挥具体建造者类构建出特定的对象电脑对象:
 */
public class Director {
    private ComputerBuilder computerBuilder;
    public void setComputerBuilder(ComputerBuilder computerBuilder){
        this.computerBuilder = computerBuilder;
    }
    public Computer getComputer(){
        return computerBuilder.getComputer();
    }
    public void buildComputer(){ 
        computerBuilder.createNewComputer();
        computerBuilder.buildCpu();
        computerBuilder.buildGpu();
        computerBuilder.buildMemory();
    }
}

测试类:

/**
 * @author Shier
 * CreateTime 2023/4/26 22:13
 * main方法中使用Director构建具体的电脑对象
 */
public class ComputerTest {
    public static void main(String[] args) {
        // 创建Director类
        Director director = new Director();

        // 具体建造者A
        ComputerBuilderA builderA = new ComputerBuilderA();
        director.setComputerBuilder(builderA); // 让DIrector类构建A的电脑配置
        director.buildComputer(); // 在Director类中进行构建
        Computer computerA = director.getComputer();
        System.out.println("电脑A的配置:");
        System.out.println(computerA.toString());

        // 创建电脑建造者B
        ComputerBuilder builderB = new ComputerBuilderB();
        director.setComputerBuilder(builderB);
        director.buildComputer();
        Computer computerB = director.getComputer();
        System.out.println("电脑B的配置:");
        System.out.println(computerB.toString());

        // 创建电脑建造者C
        ComputerBuilder builderC = new ComputerBuilderC();
        director.setComputerBuilder(builderC);
        director.buildComputer();
        Computer computerC = director.getComputer();
        System.out.println("电脑C的配置:");
        System.out.println(computerC.toString());
    }
}

最后输出结果:

image-20230426222937681

这就是一个简单的建造者模式实现,通过不同的具体建造者类构建出了三个不同的电脑对象,并实现了将复杂对象的构建与表示分离。

3、总结

适用场景:

  • 建造者模式主要用于创建一些复杂的对象,这些对象内部子对象的建造顺序通常是稳定的,但每个子对象本身的构建通常面临着复杂的变化。
  • 建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。

建造者模式优点:

  1. 可以将一个复杂对象的构造过程与其表示分离开来,并且可以使得同样的构造过程可以创建不同的表示。
  2. 建造者模式可以让客户端不必知道产品构建的细节,从而降低了系统的耦合度。
  3. 可以使用建造者模式逐步构建一个复杂的对象,从而可以控制对象构建的过程及其顺序。
  4. 可以隔离复杂对象的创建和使用,并且可以提高代码的复用性。

建造者模式缺点:

  1. 建造者模式需要为每一个需要创建的产品定义一个具体的建造者类,从而会增加系统中类的个数。
  2. 由于建造者模式要求建造者必须按照指定的顺序进行构造对象,因此可能会对其灵活性产生一定的影响。

em.out.println(“电脑C的配置:”);
System.out.println(computerC.toString());
}
}


最后输出结果:

[外链图片转存中...(img-i5ciGKgu-1685679055776)]

> 这就是一个简单的建造者模式实现,通过不同的具体建造者类构建出了三个不同的电脑对象,并实现了将复杂对象的构建与表示分离。



## 3、总结

适用场景:

- 建造者模式主要用于创建一些复杂的对象,这些对象内部子对象的建造顺序通常是稳定的,但每个子对象本身的构建通常面临着复杂的变化。
- 建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。

建造者模式优点:

1. 可以将一个复杂对象的构造过程与其表示分离开来,并且可以使得同样的构造过程可以创建不同的表示。
2. 建造者模式可以让客户端不必知道产品构建的细节,从而降低了系统的耦合度。
3. 可以使用建造者模式逐步构建一个复杂的对象,从而可以控制对象构建的过程及其顺序。
4. 可以隔离复杂对象的创建和使用,并且可以提高代码的复用性。

建造者模式缺点:

1. 建造者模式需要为每一个需要创建的产品定义一个具体的建造者类,从而会增加系统中类的个数。
2. 由于建造者模式要求建造者必须按照指定的顺序进行构造对象,因此可能会对其灵活性产生一定的影响。







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

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

相关文章

七面蚂蚁金服,超硬核面经,已拿Offer!!

刚面试了蚂蚁金服&#xff0c;给大家分享下这些硬核的面试经验 一面&#xff1a;50分钟 1.自我介绍 2.之前的实习经历提问 3.实习做过什么项目&#xff0c;负责什么 4.进程线程 5.java的垃圾回收 6.数据库简单sql语句 7.事务隔离 8.测试微信点赞 9.对测试的了解 10.编程&…

【LeetCode每日一题】——2269.找到一个数字的 K 美丽值

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 滑动窗口 二【题目难度】 简单 三【题目编号】 2269.找到一个数字的 K 美丽值 四【题目描述…

第二十二篇、基于Arduino uno,控制五线四相步进电机实现正转和反转——结果导向

0、结果 说明&#xff1a;步进电机可以旋转指定角度&#xff0c;例如转了九十度就停止&#xff0c;如果想一直转也是可以的&#xff0c;程序里面已写&#xff0c;而且也有正反转。如果是你想要的&#xff0c;可以接着往下看。 1、外观 说明&#xff1a;五线四相步进电机如下…

自然语言处理从入门到应用——文本的表示方法

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 若要利用计算机对自然语言进行处理&#xff0c;首先需要解决语言在计算机内部的存储和计算问题。字符串&#xff08;String&#xff09;是文本最自然&#xff0c;也是最常用的机内存储形式。所谓字符串&#xff0c;即字…

rtty移植到MTK OpenWRT平台

准备工具链 使用MTK Openwrt 相应平台工具链&#xff0c;不能使用buildroot的工具链&#xff0c;否则程序无法运行&#xff0c;本文MTK7621为例工具链官网下载地址 构建libev rtty依赖libev库&#xff0c;因此需要先构建libev git clone https://github.com/enki/libev.git …

C语言-外部关键字extern

extern 关键字 extern 用在全局变量或函数的声明前&#xff0c;用来说明“此变量/函数是在别处定义的&#xff0c;要在此处引用。 什么是定义&#xff0c;什么是声明? 什么是定义:所谓的定义就是为这个变量分配一块内存并给它取上一个名字&#xff0c;这个名字就是我们经…

《多传感器融合感知》一、构建自动驾驶多传感器系统

来自 &#xff1a; https://www.bilibili.com/video/BV1JY4y1R7Be/ 多传感器融合的需求多传感器硬件系统构建多传感器硬件系统的时序闭环 1. 多传感器融合的需求 自动驾驶用来解决的问题&#xff1a; 建图定位、感知问题&#xff08;路上有什么、堵不堵、好不好走…&#xff…

数据可视化系列指南之分布类图表大全

导语 随着数据在各行业中的应用越来越广泛&#xff0c;大家也逐渐认识到数据可视化在企业生产经营中的重要作用&#xff0c;在数据可视化过程中&#xff0c;图表是处理数据的重要组成部分&#xff0c;因为它们是一种将大量数据压缩为易于理解的格式的方法。数据可视化可以让受…

生态系统服务评估方法 | 人类活动影响、重大工程实施的生态成效评估(InVEST模型)

以InVEST模型结合实际项目进行由浅入深的实战技术&#xff0c;针对特点及需求进行分析&#xff0c;融合课程体系&#xff0c;对接工作实际项目及论文写作&#xff0c;解决参会者关注的重点及实际项目过程问题&#xff0c;采取逐步延伸的逻辑&#xff0c;不论您是小白亦或是已经…

数据库磁盘文件格式的设计原理内幕

引言 访问磁盘需通过系统调用来实现&#xff0c;因此通常我们需要指定目标文件的偏移量&#xff0c;然后把数据从磁盘上的形式解析成合适主存的形式。这意味着要想设计一个高效的磁盘数据结构&#xff0c;必须构造一种易于修改和解析的文件格式。在本文中&#xff0c;我们将讨论…

unicms 使用thinkphp8 重构版

unicms 有你存在 一切安好 2023年6月使用thinkphp8&#xff0c;重构了cms。php最低使用php8版。参考了多个cms结合10年的开发经验&#xff0c;打造了开箱机用&#xff0c;简单的cms系统。当然由于你能力和开发时间限制&#xff0c;肯定有bug。欢迎大家指正。我也会不定期的修改…

【线性规划模型】

线性规划模型&#xff1a;原理介绍和预测应用 引言 线性规划是运筹学中一种重要的数学优化方法&#xff0c;被广泛应用于各个领域&#xff0c;包括工业、经济、物流等。 线性规划模型的原理 线性规划模型的目标是在一组线性约束条件下&#xff0c;寻找一组变量的最优解&…

Emm_V4.2步进闭环驱动器说明书Rev1.1

一、产品介绍 1.1 产品简介&#xff1a; Emm42_V4.x步进闭环驱动器是张大头智控为满足广大用户需求而自主研发的一款稳定可靠的产品&#xff0c;它是基于上一代Emm42_V3.6版本升级而来&#xff0c;不仅延续了其优秀的FOC矢量闭环控制算法&#xff0c;更在其传统的Dir/Step控制模…

Java003——编写和运行第一个Java程序HelloWorld

一、使用记事本创建Java并运行 1.1、设置文件显示后缀名 目的是为了方便查看文件类型 1.2、创建一个HelloWorld.java文件 java程序文件都是以.java后缀结尾的 1.3、编写Java程序 编写一下程序&#xff0c;并保存 public class HelloWorld {public static void main(Strin…

100天精通Golang(基础入门篇)——第0天: 安装 Go 语言开发环境的基础教程,带你学习Golang之Hello Go !

文章目录 1. 下载 Go 语言的安装包&#xff1a;1. 安装 Go 编译器&#xff1a;- 双击 安装下一步:切换安装路径:下一步:安装等待安装完成安装完成 - 2. 测试安装是否成功&#xff1a;1. 开始学习 Go 语言&#xff1a;1. 创建项目2. 创建 类文件3. 输入类名4. 键入 下方代码块5.…

【C语言】让你不再害怕“指针”【c】【知识点整理】

目录 一.什么是指针&&为什么需要指针&#xff1f; 1.什么是指针&#xff1f; 2.为什么需要指针&#xff1f; 以一个代码为例观察地址&#xff1a;&#xff08;这里我们可以通过调试和打印两种方式观察&#xff09; 1.调试观察&#xff1a; 2.打印观察&#xff08;…

Vue.js 中的 v-if 和 v-show 有什么区别?

Vue.js 中的 v-if 和 v-show 有什么区别&#xff1f; 在 Vue.js 中&#xff0c;v-if 和 v-show 都是用来控制元素的显示和隐藏的指令。但是&#xff0c;它们之间有一些区别。本文将深入探讨 v-if 和 v-show 的区别&#xff0c;并给出一些相关的代码示例。 v-if v-if 是一种条…

python数据分析模块

python数据分析模块 Python与数据分析的关系数据分析常用模块Python数据分析常用类库1&#xff0e;数组计算的数学模块-Numpy2&#xff0e;Pandas——数据分析核心库3&#xff0e;Matplotlib——绘制数据图表的 Python 库4&#xff0e;批量处理Excel文件的模块-xlwings5&#x…

浮点型在内存中的存储,与整型存储方式竟然不同

对于整形的存储方式&#xff0c;大家可以看我的上一篇文章&#xff0c;这篇文章来介绍浮点型在内存中存储方式。 目录 1. 问题 2. 浮点型家族&#xff1a; 3. 存储方式: 4. 读取方式&#xff1a; 5. 解题 1. 问题 我们先来看一段代码&#xff1a; #include <stdio.h&…

人体姿态估计

预测人体关键点有什么作用&#xff1f; 还原人体姿态&#xff0c;输出脸部、手部的关键点坐标3D空间内&#xff0c;关键点变为3维坐标&#xff0c;可以在三维空间中还原人体姿态&#xff0c;可以实现一键换装恢复3D的人体模型实现下游任务–行为理解&#xff0c;根据姿态判断人…