【设计模式】23种设计模式——建造者模式Builder(原理讲解+应用场景介绍+案例介绍+Java代码实现)

news2024/11/25 2:40:02

介绍

  • 建造者模式又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同属性的对象
  • 建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,不需要知道内部的具体构建细节(如用户在选购汽车的时候,只需要选择好方向盘、轮胎、发动机类型,不需要知道零件是怎么制造出来的)

出场角色

在这里插入图片描述

  • Product(产品):一个具体的产品对象
  • Builder (抽象建造者): 创建指定roduct对象的各个部件的接口/抽象类,用于将建造流程整理出来,但是不在乎建造细节,即只声明抽象方法
  • ConcreteBuilder (具体建造者): 实现抽象建造者的接口
  • Director(指挥者/监工): 使用Builder接口来生成示例。它主要是用于创建一个复杂的对象。它主要有两个作用,一是隔离客户与对象的生产过程,二是控制产品对象的生产过程。
  • Client(使用者):让Director干活,使用建造者模式

案例

盖房子需求

房子有多种类型,比如普通房,高楼,别墅,建房子的过程包括打桩砌墙封顶多个步骤,不同类型的房子建造的流程差不多,但是里面的方法有所差异

原始实现

在这里插入图片描述

【抽象房子类】

package com.atguigu.builder;

public abstract class AbstractHouse {

   /**
    * 打地基
    */
   public abstract void buildBasic();

   /**
    * 砌墙
    */
   public abstract void buildWalls();

   /**
    * 封顶
    */
   public abstract void roofed();

   public void build() {
      buildBasic();
      buildWalls();
      roofed();
   }

}

【普通房子】

package com.atguigu.builder;

public class CommonHouse extends AbstractHouse {

   @Override
   public void buildBasic() {
      System.out.println(" 普通房子打地基 ");
   }

   @Override
   public void buildWalls() {
      System.out.println(" 普通房子砌墙 ");
   }

   @Override
   public void roofed() {
      System.out.println(" 普通房子封顶 ");
   }

}

【高楼】

package com.atguigu.builder;

public class HignBuilding extends AbstractHouse {

   @Override
   public void buildBasic() {
      System.out.println(" 高楼打地基 ");
   }

   @Override
   public void buildWalls() {
      System.out.println(" 高楼房子砌墙 ");
   }

   @Override
   public void roofed() {
      System.out.println(" 高楼房子封顶 ");
   }

}

【主类】

package com.atguigu.builder;

public class Client {

   public static void main(String[] args) {
      CommonHouse commonHouse = new CommonHouse();
      commonHouse.build();
      System.out.println("-------------------------------------------------------------------------------------------------------");
      HignBuilding highBuilding = new HignBuilding();
      highBuilding.build();
   }

}

【运行】

 普通房子打地基 
 普通房子砌墙 
 普通房子封顶 
-------------------------------------------------------------------------------------------------------
 高楼打地基 
 高楼房子砌墙 
 高楼房子封顶 

Process finished with exit code 0

分析

  • 优点:比较好理解,简单易操作
  • 缺点:程序结构过于简单,没有设计缓存层对象,程序的扩展和维护不好。这种设计方案,把产品(即:房子) 和 创建产品的过程(即:建房子流程) 封装在一起,耦合性增强了
  • 改进:使用建造者模式,将产品和产品建造过程解耦

建造者模式

在这里插入图片描述

【抽象房子】

package com.atguigu.builder.improve;

/**
 * 产品->Product
 */
public class House {
    private String basic;
    private String wall;
    private String roofed;

    public String getBasic() {
        return basic;
    }

    public void setBasic(String basic) {
        this.basic = basic;
    }

    public String getWall() {
        return wall;
    }

    public void setWall(String wall) {
        this.wall = wall;
    }

    public String getRoofed() {
        return roofed;
    }

    public void setRoofed(String roofed) {
        this.roofed = roofed;
    }

    public House(String basic, String wall, String roofed) {
        this.basic = basic;
        this.wall = wall;
        this.roofed = roofed;
    }

    public House() {
    }

    @Override
    public String toString() {
        return "House{" +
                "basic='" + basic + '\'' +
                ", wall='" + wall + '\'' +
                ", roofed='" + roofed + '\'' +
                '}';
    }
}

【抽象建造者】

package com.atguigu.builder.improve;


/**
 * 抽象的建造者
 */
public abstract class HouseBuilder {
   /**
    * 组合House
    */
   protected House house = new House();

   //-------------------------将建造的流程写好--------------------------

   /**
    * 打地基
    */
   public abstract void buildBasic();

   /**
    * 砌墙
    */
   public abstract void buildWalls();

   /**
    * 封顶
    */
   public abstract void roofed();

   /**
    * 建造好房子后将产品(房子) 返回
    * @return
    */
   public House buildHouse() {
      return house;
   }

}

【具体建造者:普通房】

package com.atguigu.builder.improve;

/**
 * 具体建造者
 */
public class CommonHouse extends HouseBuilder {

   @Override
   public void buildBasic() {
      System.out.println(" 普通房子打地基5米 ");
      super.house.setBasic("地基5米");
   }

   @Override
   public void buildWalls() {
      System.out.println(" 普通房子砌墙10cm ");
      super.house.setWall("墙10cm");
   }

   @Override
   public void roofed() {
      System.out.println(" 普通房子屋顶 ");
      super.house.setRoofed("普通房子屋顶");
   }

}

【具体建造者:高楼】

package com.atguigu.builder.improve;

/**
 * 具体建造者
 */
public class HighBuilding extends HouseBuilder {

   @Override
   public void buildBasic() {
      System.out.println(" 高楼的打地基100米 ");
      super.house.setBasic("地基100米");
   }

   @Override
   public void buildWalls() {
      System.out.println(" 高楼的砌墙20cm ");
      super.house.setWall("墙20cm");
   }

   @Override
   public void roofed() {
      System.out.println(" 高楼的透明屋顶 ");
      super.house.setRoofed("透明屋顶");
   }

}

【指挥者】

package com.atguigu.builder.improve;

/**
 * 指挥者,调用制作方法,返回产品
 */
public class HouseDirector {
   /**
    * 聚合
    */
   HouseBuilder houseBuilder = null;

   /**
    * 方式一:构造器传入 houseBuilder
    * @param houseBuilder
    */
   public HouseDirector(HouseBuilder houseBuilder) {
      this.houseBuilder = houseBuilder;
   }

   /**
    * 方式二:通过setter 传入 houseBuilder
    * @param houseBuilder
    */
   public void setHouseBuilder(HouseBuilder houseBuilder) {
      this.houseBuilder = houseBuilder;
   }

   /**
    * 指挥者统一管理建造房子的流程
    * @return
    */
   public House constructHouse() {
      houseBuilder.buildBasic();
      houseBuilder.buildWalls();
      houseBuilder.roofed();
      return houseBuilder.buildHouse();
   }


}

【客户端】

package com.atguigu.builder.improve;

public class Client {
    public static void main(String[] args) {

        ///盖普通房子
        //准备创建房子的指挥者
        HouseDirector houseDirector = new HouseDirector(new CommonHouse());
        //完成盖房子,返回产品(普通房子)
        House commonHouse = houseDirector.constructHouse();
        System.out.println("普通房子:" + commonHouse.toString());

        System.out.println("---------------------------------------------------------------------------------------------");
        ///盖高楼
        //重置建造者,改成修高楼
        houseDirector.setHouseBuilder(new HighBuilding());
        //完成盖房子,返回产品(高楼)
        House highBuilding = houseDirector.constructHouse();
        System.out.println("高楼:" + highBuilding.toString());
    }
}

【运行】

 普通房子打地基5米 
 普通房子砌墙10cm 
 普通房子屋顶 
普通房子:House{basic='地基5米', wall='墙10cm', roofed='普通房子屋顶'}
---------------------------------------------------------------------------------------------
 高楼的打地基100米 
 高楼的砌墙20cm 
 高楼的透明屋顶 
高楼:House{basic='地基100米', wall='墙20cm', roofed='透明屋顶'}

Process finished with exit code 0

文档编写

在这里插入图片描述

【抽象建造者】

package com.atguigu.builder.Sample;

public abstract class Builder {
    /**
     * 编写标题
     * @param title
     */
    public abstract void makeTitle(String title);

    /**
     * 编写字符串
     * @param str
     */
    public abstract void makeString(String str);

    /**
     * 编写条目
     * @param items
     */
    public abstract void makeItems(String[] items);

    /**
     * 完成文档编写
     */
    public abstract void close();
}

【具体建造者一】

package com.atguigu.builder.Sample;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class HTMLBuilder extends Builder {
    /**
     * 文件名
     */
    private String filename;
    /**
     * 用于编写文件的PrintWriter
     */
    private PrintWriter writer;

    /**
     * HTML文件的标题
     *
     * @param title
     */
    public void makeTitle(String title) {
        // 将标题作为文件名
        filename = title + ".html";
        try {
            // 生成 PrintWriter
            writer = new PrintWriter(new FileWriter(filename));
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 输出标题
        writer.println("<html><head><title>" + title + "</title></head><body>");
        writer.println("<h1>" + title + "</h1>");
    }

    /**
     * HTML文件中的字符串
     *
     * @param str
     */
    public void makeString(String str) {
        // 用<p>标签输出
        writer.println("<p>" + str + "</p>");
    }

    /**
     * HTML文件中的条目
     *
     * @param items
     */
    public void makeItems(String[] items) {
        // 用<ul>和<li>输出
        writer.println("<ul>");
        for (int i = 0; i < items.length; i++) {
            writer.println("<li>" + items[i] + "</li>");
        }
        writer.println("</ul>");
    }

    /**
     * 完成文档
     */
    public void close() {
        // 关闭标签
        writer.println("</body></html>");
        // 关闭文件
        writer.close();
    }

    public String getResult() {
        // 编写完成的文档
        return filename;
    }
}

【具体建造者二】

package com.atguigu.builder.Sample;

public class TextBuilder extends Builder {
    /**
     * 文档内容保存在该字段中
     */
    private StringBuffer buffer = new StringBuffer();

    /**
     * 纯文本的标题
     *
     * @param title
     */
    public void makeTitle(String title) {
        // 装饰线
        buffer.append("==============================\n");
        // 为标题添加『』
        buffer.append("『" + title + "』\n");
        // 换行
        buffer.append("\n");
    }

    /**
     * 纯文本的字符串
     *
     * @param str
     */
    public void makeString(String str) {
        // 为字符串添加■
        buffer.append('■' + str + "\n");
        // 换行
        buffer.append("\n");
    }

    /**
     * 纯文本的条目
     *
     * @param items
     */
    public void makeItems(String[] items) {
        for (int i = 0; i < items.length; i++) {
            // 为条目添加・
            buffer.append(" ・" + items[i] + "\n");
        }
        // 换行
        buffer.append("\n");
    }

    /**
     * 完成文档
     */
    public void close() {
        // 装饰线
        buffer.append("==============================\n");
    }

    /**
     * 完成的文档
     * @return
     */
    public String getResult() {
        // 将StringBuffer变换为String
        return buffer.toString();
    }
}

【指挥者】

package com.atguigu.builder.Sample;

/**
 * 由于TextBuilder和HTMLBuilder都是Builder的子类,因此Director 仅仅使用Builder的方法即可编写文档。
 * Director并不关心实际编写文档的到底是TextBuilder还是HTMBuilder
 */
public class Director {
    private Builder builder;

    /**
     * 实际上不会将 Builder类的实例作为参数传递给 Director类。这是因为 Builder 类是抽象类,是无法生成其实例的。
     * 实际上传递给 Director 类的是 Builder类的子类
     * @param builder
     */
    public Director(Builder builder) {
        this.builder = builder;
    }

    /**
     * 编写文档
     */
    public void construct() {
        // 标题
        builder.makeTitle("Greeting");
        // 字符串
        builder.makeString("从早上至下午");
        // 条目
        builder.makeItems(new String[]{
                "早上好。",
                "下午好。",
        });
        // 其他字符串
        builder.makeString("晚上");
        // 其他条目
        builder.makeItems(new String[]{
                "晚上好。",
                "晚安。",
                "再见。",
        });
        // 完成文档
        builder.close();
    }
}

【测试】

package com.atguigu.builder.Sample;

/**
 * Builder模式测试
 */
public class Main {
    public static void main(String[] args) {
        String type = "plain";
        if (type.equals("plain")) {
            TextBuilder textbuilder = new TextBuilder();
            Director director = new Director(textbuilder);
            director.construct();
            String result = textbuilder.getResult();
            System.out.println(result);
        } else if (type.equals("html")) {
            HTMLBuilder htmlbuilder = new HTMLBuilder();
            Director director = new Director(htmlbuilder);
            director.construct();
            String filename = htmlbuilder.getResult();
            System.out.println(filename + "文件编写完成。");
        } else {
            usage();
            System.exit(0);
        }
    }

    public static void usage() {
        System.out.println("Usage: java Main plain      编写纯文本文档");
        System.out.println("Usage: java Main html       编写HTML文档");
    }
}

【运行】

type = “plain”

==============================
『Greeting』

■从早上至下午

 ・早上好。
 ・下午好。

■晚上

 ・晚上好。
 ・晚安。
 ・再见。

==============================


Process finished with exit code 0

type = “html”

<html>
<head><title>Greeting</title></head>
<body>
<h1>Greeting</h1>
<p>从早上至下午</p>
<ul>
    <li>早上好。</li>
    <li>下午好。</li>
</ul>
<p>晚上</p>
<ul>
    <li>晚上好。</li>
    <li>晚安。</li>
    <li>再见。</li>
</ul>
</body>
</html>

【分析】

  • Main类并不知道Builder类,它只是调用了Direct 类的construct 方法这样,Director类就会开始工作(Main类对此一无所知),并完成文档的编写
  • Director类知道Builder类,它调用Builder类的方法来编写文档,但它并不知道它所使用的类到底是 TextBuilder类、HTMLBuilder类还是其他 Builder类的子类,而且也没有必要知道,因为Director类只使用Builder类的方法
  • 不论是将 TextBuilder 的实例传递给 Director,还是将HTMLBuilder类的实例传递给 Director,它都可以正常工作,原因正是Director类不知道Builder类的具体的子类。正是因为不知道才能够替换,正是因为可以替换,组件才具有高价值。作为设计人员,我们必须时刻关注这种“可替换性”

拓展一

【要求】

请修改 Builder类TetBuilder类和HTMLBuilder类,确保“在调用makeString 方法、makeItems 方法和close方法之前必须且只能调用一次makeTitle方法”

【Builder 类】

public abstract class Builder {
    private boolean initialized = false;
    public void makeTitle(String title) {
        if (!initialized) {
            buildTitle(title);
            initialized = true;
        }
    }
    public void makeString(String str) {
        if (initialized) {
            buildString(str);
        }
    }
    public void makeItems(String[] items) {
        if (initialized) {
            buildItems(items);
        }
    }
    public void close() {
        if (initialized) {
            buildDone();
        }
    }
    protected abstract void buildTitle(String title);
    protected abstract void buildString(String str);
    protected abstract void buildItems(String[] items);
    protected abstract void buildDone();
}

【其他两个类】

其他两个类的方法内容还是一样的,修改一下方法名,将抽象Builder的方法实现即可

问题

问:编写的文档被保存在了buffer字段中,但buffer字段并非是String类型的,而是StringBuffer类型的,请问是为什么呢?如果使用了 string 类型会有什么问题呢?

答:使用String类型保存文档会存在效率问题,因为String类型是不可变的,每次对String进行修改都会生成一个新的String对象,而StringBuffer类型是可变的,可以进行高效的字符串拼接和修改。因此,为了保证文档的高效修改和拼接,使用StringBuffer类型更加合适

JDK源码中使用建造者模式

在这里插入图片描述
在这里插入图片描述

  • Appendable 接口定义了多个append方法(抽象方法),即Appendable 为抽象建造者,定义了抽象方法
  • AbstractStringBuilder 实现了 Appendable 接口方法,这里的AbstractStringBuilder 已经是建造者,只是不能实例化
  • StringBuilder 即充当了指挥者角色,同时充当了具体的建造者,建造方法的实现是由 AbstractStringBuilder 完成,而StringBuilder 继承了AbstractStringBuilder

在这里插入图片描述

【总结】

  • JDK中使用设计模式的方式不一定和标准的一样(设计模式可能是更后面提出来的),但是核心思想大同小异

注意事项

  • 客户端(使用程序)不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
  • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象
  • 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程
  • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程系统扩展方便,符合“开闭原则“
  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化导致系统变得很庞大,因此在这种情况下,要考虑是否选择建造者模式

【抽象工厂模式vs建造者模式】

  • 抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品: 具有不同分类维度的产品组合,采用抽象工厂模式不需要关心构建过程,只关心什么产品由什么工厂生产即可
  • 建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品
  • 两种模式都用来生成复杂的实例

文章说明

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

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

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

相关文章

【PHP面试题79】在Linux中如何设置MySQL和PHP服务开机启动

文章目录 &#x1f680;一、前言&#x1f680;二、设置MySQL服务开机启动&#x1f50e;2.1 打开终端&#x1f50e;2.2 编辑MySQL配置文件&#x1f50e;2.3 修改配置文件&#x1f50e;2.4 检查MySQL服务是否已启动&#x1f50e;2.5 设置MySQL服务开机启动 &#x1f680;三、设置…

C# Modbus通信从入门到精通(12)——Modbus ASCII协议原理

Modbus ASCII是串行链路上的协议,也就是说ModbusASCII是通过串口通信来实现的,它可以通过RS232、RS485物理层的接口来实现,同时它也是一个主从协议,在同一时间总线上只能有一个主站和一个或多个(最多247)个从站。Modbus通信总是由主站发起,从站没有接收到主站的请求时不…

NOAA国家强风暴实验室的天气雷达研究历史(1962年~2016年)

一、1962年-NSSP开始研究WSR-57 美国气象局国家严重风暴项目(NSSP)的一小群研究人员从堪萨斯城搬到俄克拉荷马州诺曼的天气雷达实验室,并开始研究最近安装的研究天气监视雷达-1957(WSR-57)。 二、1964年-NSSL开发的脉冲多普勒雷达技术 1956年,康奈尔航空实验室建造了一…

C++OpenCV(2):图像处理基础概念与操作

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 &#x1f506; OpenCV项目地址及源代码&#xff1a;点击这里 文章目录 图形读取与显示加载图片显示图片打印图片信息保存图片 色彩模型转换RGB颜色模型HSV颜色模型HLS模型LAB模型 图像像素读写操作像素算数运…

python机器学习(二)特征工程、K-近邻算法、KNN工作流程、scikit-learn实现K近邻算法、K值选择、距离计算、KD树

特征工程 把特征转换为机器容易识别的数据&#xff0c;把特征a转化为机器容易读懂、量化的语言 归一化Min-Max 将原始数据映射到[0,1]之间 X ′ x − m i n m a x − m i n X \frac{x-min}{max-min} X′max−minx−min​ 但是归一化是有弊端的&#xff0c;比如有一个值错误…

OJ练习第142题——路径总和 II

113. 路径总和 II 力扣链接&#xff1a;113. 路径总和 II 题目描述 给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 Java代码&#xff08;深度优先搜…

基于linux下的高并发服务器开发(第三章)- 3.8 线程同步

sellticket.c /*使用多线程实现买票的案例。有3个窗口&#xff0c;一共是100张票。 */#include <stdio.h> #include <pthread.h> #include <unistd.h>// 全局变量&#xff0c;所有的线程都共享这一份资源。 int tickets 100;void * sellticket(void * arg)…

后处理材质球:黄金螺旋分割线和参考图

后处理材质球&#xff1a;黄金螺旋分割线和参考图 Begin Object Class/Script/UnrealEd.MaterialGraphNode Name"MaterialGraphNode_0"Begin Object Class/Script/Engine.MaterialExpressionLinearInterpolate Name"MaterialExpressionLinearInterpolate_1&qu…

(202307)wonderful-sql:初识数据库(task1)

学习知识 初识数据库 关系型数据库简介 特点是由行和列组成的二维表来管理数据&#xff0c;这种类型的 DBMS 称为关系数据库管理系统&#xff08;Relational Database Management System&#xff0c;RDBMS&#xff09;。本课程将向大家介绍使用 SQL 语言的数据库管理系统&am…

No5:学习过程中基础语法积累

文章目录 基础语法&#xff1a;对象对象构建和数据封装 集合列表截取输出&#xff08;特色是数据可变即可重新赋值&#xff09;元组截取输出&#xff08;元组特色是数据不可变&#xff09;字典&#xff08;根据key取value&#xff09; 字符串函数 基础语法&#xff1a;对象 对…

【动态规划part04】| 背包问题理论基础、416.分割等和子集

目录 &#x1f388;背包问题理论基础 &#x1f45c;01背包 ✨二维dp数组01背包 ✨一维dp数组01背包&#xff08;滚动数组&#xff09; &#x1f388;LeetCode416.分割等和子集 &#x1f388;背包问题理论基础 &#x1f45c;01背包 有n件物品和一个最多能背重量为w 的背…

AUTOSAR从入门到精通-【应用篇】基于 LIN 总线的汽车自动天窗防夹控制系统的设计与实现

目录 前言 天窗控制系统的 LIN 总线 2.1 LIN 总线概述 2.2 LIN 总线协议规范 2.3 防夹控制系统的 LIN 总线 2.4 系统 LIN 网络测试 天窗防夹控制系统整体设计方案 3.1 天窗防夹控制系统功能 3.2 控制系统总体设计 3.2.1 系统结构 3.2.2 天窗防夹控制器 3.2.3 天窗传…

小黑子—JavaWeb:第二章 Maven与MyBatis

JavaWeb入门2.0 1.Maven1.1 Maven 简介1.2 Maven 安装配置1.3 Maven 基本使用1.3.1 Maven常用命令1.3.2 Maven生命周期 1.4 IDEA 配置 Maven1.4.1 配置 Maven 环境1.4.2 Maven 坐标详情1.4.3 IDEA 创建Maven项目1.4.4 IDEA 导入Maven文件1.4.5 配置Maven-Helper 插件 1.5 依赖管…

逻辑斯特回归

*分类是离散的&#xff0c;回归是连续的 下载数据集 trainTrue&#xff1a;下载训练集 逻辑斯蒂函数保证输出值在0-1之间 能够把实数值映射到0-1之间 导函数类似正态分布 其他饱和函数sigmoid functions 循环神经网络经常使用tanh函数 与线性回归区别 塞戈马无参数&#x…

《嵌入式 - 工具》J-link读写MCU内部Flash

1 J-Link简介 J-Link是SEGGER公司为支持仿真ARM内核芯片推出的JTAG仿真器。配合IAR EWAR&#xff0c;ADS&#xff0c;KEIL&#xff0c;WINARM&#xff0c;RealView等集成开发环境支持所有ARM7/ARM9/ARM11,Cortex M0/M1/M3/M4, Cortex A5/A8/A9等内核芯片的仿真&#xff0c;是学…

VirtualBox 7.0.10 使用宿主机物理硬盘

方法&#xff1a; 利用virtualbox的管理工具&#xff0c;将宿主机脱机后的物理硬盘&#xff0c;映射为一个vmdk&#xff0c;然后在vitrualbox中注册该vmdk&#xff0c;然后分配给虚拟机使用。 1. 右键单击window桌面左下角&#xff0c;选择 Windows PowerShell (管理员) 2. c…

第一章 函数的概念

文章目录 考点1、定义域2、对应法则 一、函数的概念1、自变量 x , 因变量 y&#xff0c;一一对应&#xff0c;因此有公式 y f (x)2、定义域具体函数的定义域 &#xff08;送分题&#xff09; 真题1、2、3、4、抽象函数的定义域 真题1、2、 3、根据函数的对应法则求函数表达式题…

会声会影VideoStudio2023中文旗舰版有哪些新功能及最低系统配置要求

会声会影VideoStudio2023中文旗舰版使用起来很有趣。它很容易使用&#xff0c;但仍然给你很多功能和力量。会声会影VideoStudio2023中文旗舰版让我与世界分享我的想法&#xff01;“这个产品的功能非常多&#xff0c;我几乎没有触及它的表面&#xff0c;我可以做大量的编辑、色…

js ==运算规则

let a {name: zhangsan,valueOf(){return 100;} }; let b 100; console.log(ab); //true let a {value: 1,valueOf: function() {return this.value;} };console.log(a 1 && a 2 && a 3); // 输出 true

macOS Sonoma 14 beta 3 (23A5286i) ISO、IPSW、PKG 下载,公共测试版现已推出

macOS Sonoma 14 beta 3 (23A5286i) ISO、IPSW、PKG 下载&#xff0c;公共测试版现已推出 本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装…