【Go实现】实践GoF的23种设计模式:建造者模式

原创 元闰子的邀请 2022-05-05 22:33

上一篇:【Go实现】实践GoF的23种设计模式:单例模式

简单的分布式应用系统(示例代码工程):https://github.com/ruanrunxue/Practice-Design-Pattern--Go-Implementation

简述

在程序设计中,我们会经常遇到一些复杂的对象,其中有很多成员属性,甚至嵌套着多个复杂的对象。这种情况下,创建这个复杂对象就会变得很繁琐。对于 C++/Java 而言,最常见的表现就是构造函数有着长长的参数列表:

MyObject obj = new MyObject(param1, param2, param3, param4, param5, param6, ...)

对于 Go 语言来说,最常见的表现就是多层的嵌套实例化:

obj := &MyObject{
  Field1: &Field1 {
    Param1: &Param1 {
      Val: 0,
    },
    Param2: &Param2 {
      Val: 1,
    },
    ...
  },
  Field2: &Field2 {
    Param3: &Param3 {
      Val: 2,
    },
    ...
  },
  ...
}

上述的对象创建方法有两个明显的缺点:(1)对使用者不友好,使用者在创建对象时需要知道的细节太多;(2)代码可读性很差

针对这种对象成员较多,创建对象逻辑较为繁琐的场景,非常适合使用建造者模式来进行优化。

建造者模式的作用有如下几个:

1、封装复杂对象的创建过程,使对象使用者不感知复杂的创建逻辑。
2、可以一步步按照顺序对成员进行赋值,或者创建嵌套对象,并最终完成目标对象的创建。
3、对多个对象复用同样的对象创建逻辑。
其中,第1和第2点比较常用,下面对建造者模式的实现也主要是针对这两点进行示例。

UML 结构

代码实现

示例

在简单的分布式应用系统(示例代码工程)中,我们定义了服务注册中心,提供服务注册、去注册、更新、 发现等功能。要实现这些功能,服务注册中心就必须保存服务的信息,我们把这些信息放在了 ServiceProfile 这个数据结构上,定义如下:

// demo/service/registry/model/service_profile.go
// ServiceProfile 服务档案,其中服务ID唯一标识一个服务实例,一种服务类型可以有多个服务实例
type ServiceProfile struct {
    Id       string           // 服务ID
    Type     ServiceType      // 服务类型
    Status   ServiceStatus    // 服务状态
    Endpoint network.Endpoint // 服务Endpoint
    Region   *Region          // 服务所属region
    Priority int              // 服务优先级,范围0~100,值越低,优先级越高
    Load     int              // 服务负载,负载越高表示服务处理的业务压力越大
}

// demo/service/registry/model/region.go
// Region 值对象,每个服务都唯一属于一个Region
type Region struct {
 Id      string
 Name    string
 Country string
}

// demo/network/endpoint.go
// Endpoint 值对象,其中ip和port属性为不可变,如果需要变更,需要整对象替换
type Endpoint struct {
 ip   string
 port int
}

实现

如果按照直接实例化方式应该是这样的:

// 多层的嵌套实例化
profile := &ServiceProfile{
 Id:       "service1",
 Type:     "order",
 Status:   Normal,
 Endpoint: network.EndpointOf("192.168.0.1"8080),
 Region: &Region{ // 需要知道对象的实现细节
  Id:      "region1",
  Name:    "beijing",
  Country: "China",
 },
 Priority: 1,
 Load:     100,
}

虽然 ServiceProfile 结构体嵌套的层次不多,但是从上述直接实例化的代码来看,确实存在对使用者不友好代码可读性较差的缺点。比如,使用者必须先对 Endpoint 和 Region 进行实例化,这实际上是将 ServiceProfile 的实现细节暴露给使用者了。
下面我们引入建造者模式对代码进行优化重构:

// demo/service/registry/model/service_profile.go
// 关键点1: 为ServiceProfile定义一个Builder对象
type serviceProfileBuild struct {
    // 关键点2: 将ServiceProfile作为Builder的成员属性
 profile *ServiceProfile
}

// 关键点3: 定义构建ServiceProfile的方法
func (s *serviceProfileBuild) WithId(id string) *serviceProfileBuild {
 s.profile.Id = id
    // 关键点4: 返回Builder接收者指针,支持链式调用
 return s
}

func (s *serviceProfileBuild) WithType(serviceType ServiceType) *serviceProfileBuild {
 s.profile.Type = serviceType
 return s
}

func (s *serviceProfileBuild) WithStatus(status ServiceStatus) *serviceProfileBuild {
 s.profile.Status = status
 return s
}

func (s *serviceProfileBuild) WithEndpoint(ip string, port int) *serviceProfileBuild {
 s.profile.Endpoint = network.EndpointOf(ip, port)
 return s
}

func (s *serviceProfileBuild) WithRegion(regionId, regionName, regionCountry) *serviceProfileBuild {
    s.profile.Region = &Region{Id: regionId, Name: regionName, Country: regionCountry}
 return s
}

func (s *serviceProfileBuild) WithPriority(priority int) *serviceProfileBuild {
 s.profile.Priority = priority
 return s
}

func (s *serviceProfileBuild) WithLoad(load int) *serviceProfileBuild {
 s.profile.Load = load
 return s
}

// 关键点5: 定义Build方法,在链式调用的最后调用,返回构建好的ServiceProfile
func (s *serviceProfileBuild) Build() *ServiceProfile {
 return s.profile
}

// 关键点6: 定义一个实例化Builder对象的工厂方法
func NewServiceProfileBuilder() *serviceProfileBuild {
 return &serviceProfileBuild{profile: &ServiceProfile{}}
}

实现建造者模式有 6 个关键点:

  1. 为 ServiceProfile 定义一个 Builder 对象 serviceProfileBuild,通常我们将它设计为包内可见,来限制客户端的滥用。
  2. 把需要构建的 ServiceProfile 作为 Builder 对象 serviceProfileBuild 的成员属性,用来存储构建过程中的状态。
  3. 为 Builder 对象 serviceProfileBuild 定义用来构建 ServiceProfile 的一系列方法,上述代码中我们使用了 WithXXX 的风格。
  4. 在构建方法中返回 Builder 对象指针本身,也即接收者指针,用来支持链式调用,提升客户端代码的简洁性。
  5. 为 Builder 对象定义 Build() 方法,返回构建好的 ServiceProfile 实例,在链式调用的最后调用。
  6. 定义一个实例化 Builder 对象的工厂方法 NewServiceProfileBuilder()

那么,使用建造者模式实例化逻辑是这样的:

// 建造者模式的实例化方法
profile := NewServiceProfileBuilder().
                WithId("service1").
                WithType("order").
                WithStatus(Normal).
                WithEndpoint("192.168.0.1"8080).
                WithRegion("region1""beijing""China").
                WithPriority(1).
                WithLoad(100).
                Build()

当使用建造者模式来进行对象创建时,使用者不再需要知道对象具体的实现细节(这里体现为无须预先实例化 Endpoint 和 Region 对象),代码可读性、简洁性也更好了。

扩展

Functional Options 模式

进一步思考,其实前文提到的建造者实现方式,还有 2 个待改进点:

  1. 我们额外新增了一个 Builder 对象,如果能够把 Builder 对象省略掉,同时又能避免长长的入参列表就更好了。
  2. 熟悉 Java 的同学应该能够感觉出来,这种实现具有很强的“Java 风格”。并非说这种风格不好,而是在 Go 中理应有更具“Go 风格”的建造者模式实现。

针对这两点,我们可以通过 Functional Options 模式 来优化。Functional Options 模式也是用来构建对象的,这里我们也把它看成是建造者模式的一种扩展。它利用了 Go 语言中函数作为一等公民的特点,结合函数的可变参数,达到了优化上述 2 个改进点的目的。
使用 Functional Options 模式的实现是这样的:

// demo/service/registry/model/service_profile_functional_options.go
// 关键点1: 定义构建ServiceProfile的functional option,以*ServiceProfile作为入参的函数
type ServiceProfileOption func(profile *ServiceProfile)

// 关键点2: 定义实例化ServiceProfile的工厂方法,使用ServiceProfileOption作为可变入参
func NewServiceProfile(svcId string, svcType ServiceType, options ...ServiceProfileOption) *ServiceProfile {
    
// 关键3: 可为特定的字段提供默认值
 profile := &ServiceProfile{
  Id:       svcId,
  Type:     svcType,
  Status:   Normal,
  Endpoint: network.EndpointOf(
"192.168.0.1"80),
  Region:   &Region{Id: 
"region1", Name: "beijing", Country: "China"},
  Priority: 
1,
  Load:     
100,
 }
    
// 关键点4: 通过ServiceProfileOption来修改字段
 
for _, option := range options {
  option(profile)
 }
 
return profile
}

// 关键点5: 定义一系列构建ServiceProfile的方法,在ServiceProfileOption实现构建逻辑,并返回ServiceProfileOption
func Status(status ServiceStatus) ServiceProfileOption {
 
return func(profile *ServiceProfile) {
  profile.Status = status
 }
}

func Endpoint(ip string, port int) ServiceProfileOption {
 
return func(profile *ServiceProfile) {
  profile.Endpoint = network.EndpointOf(ip, port)
 }
}

func SvcRegion(svcId, svcName, svcCountry string) ServiceProfileOption {
 
return func(profile *ServiceProfile) {
  profile.Region = &Region{
   Id:      svcId,
   Name:    svcName,
   Country: svcCountry,
  }
 }
}

func Priority(priority int) ServiceProfileOption {
 
return func(profile *ServiceProfile) {
  profile.Priority = priority
 }
}

func Load(load int) ServiceProfileOption {
 
return func(profile *ServiceProfile) {
  profile.Load = load
 }
}

实现 Functional Options 模式有 5 个关键点:

  1. 定义 Functional Option 类型 ServiceProfileOption,本质上是一个入参为构建对象 ServiceProfile 的指针类型。(注意必须是指针类型,值类型无法达到修改目的)
  2. 定义构建 ServiceProfile 的工厂方法,以 ServiceProfileOption 的可变参数作为入参。函数的可变参数就意味着可以不传参,因此一些必须赋值的属性建议还是定义对应的函数入参。
  3. 可为特定的属性提供默认值,这种做法在 为配置对象赋值的场景 比较常见。
  4. 在工厂方法中,通过 for 循环利用 ServiceProfileOption 完成构建对象的赋值。
  5. 定义一系列的构建方法,以需要构建的属性作为入参,返回 ServiceProfileOption 对象,并在ServiceProfileOption 中实现属性赋值。

Functional Options 模式 的实例化逻辑是这样的:

// Functional Options 模式的实例化逻辑
profile := NewServiceProfile("service1""order",
 Status(Normal),
 Endpoint("192.168.0.1"8080),
 SvcRegion("region1""beijing""China"),
 Priority(1),
 Load(100))

相比于传统的建造者模式,Functional Options 模式的使用方式明显更加的简洁,也更具“Go 风格”了。

Fluent API 模式

前文中,不管是传统的建造者模式,还是 Functional Options 模式,我们都没有限定属性的构建顺序,比如:

// 传统建造者模式不限定属性的构建顺序
profile := NewServiceProfileBuilder().
                WithPriority(1).  // 先构建Priority也完全没问题
                WithId("service1").
                ...
// Functional Options 模式也不限定属性的构建顺序
profile := NewServiceProfile("service1""order",
    Priority(1),  // 先构建Priority也完全没问题
 Status(Normal),
    ...

但是在一些特定的场景,对象的属性是要求有一定的构建顺序的,如果违反了顺序,可能会导致一些隐藏的错误。
当然,我们可以与使用者的约定好属性构建的顺序,但这种约定是不可靠的,你很难保证使用者会一直遵守该约定。所以,更好的方法应该是通过接口的设计来解决问题, Fluent API 模式 诞生了。
下面,我们使用 Fluent API 模式进行实现:

// demo/service/registry/model/service_profile_fluent_api.go
type (
    // 关键点1: 为ServiceProfile定义一个Builder对象
 fluentServiceProfileBuilder struct {
        // 关键点2: 将ServiceProfile作为Builder的成员属性
  profile *ServiceProfile
 }
    // 关键点3: 定义一系列构建属性的fluent接口,通过方法的返回值控制属性的构建顺序
 idBuilder interface {
  WithId(id string) typeBuilder
 }
 typeBuilder interface {
  WithType(svcType ServiceType) statusBuilder
 }
 statusBuilder interface {
  WithStatus(status ServiceStatus) endpointBuilder
 }
 endpointBuilder interface {
  WithEndpoint(ip string, port int) regionBuilder
 }
 regionBuilder interface {
  WithRegion(regionId, regionName, regionCountry string) priorityBuilder
 }
 priorityBuilder interface {
  WithPriority(priority int) loadBuilder
 }
 loadBuilder interface {
  WithLoad(load int) endBuilder
 }
 // 关键点4: 定义一个fluent接口返回完成构建的ServiceProfile,在最后调用链的最后调用
 endBuilder interface {
  Build() *ServiceProfile
 }
)

// 关键点5: 为Builder定义一系列构建方法,也即实现关键点3中定义的Fluent接口
func (f *fluentServiceProfileBuilder) WithId(id string) typeBuilder {
 f.profile.Id = id
 return f
}

func (f *fluentServiceProfileBuilder) WithType(svcType ServiceType) statusBuilder {
 f.profile.Type = svcType
 return f
}

func (f *fluentServiceProfileBuilder) WithStatus(status ServiceStatus) endpointBuilder {
 f.profile.Status = status
 return f
}

func (f *fluentServiceProfileBuilder) WithEndpoint(ip string, port int) regionBuilder {
 f.profile.Endpoint = network.EndpointOf(ip, port)
 return f
}

func (f *fluentServiceProfileBuilder) WithRegion(regionId, regionName, regionCountry string) priorityBuilder {
 f.profile.Region = &Region{
  Id:      regionId,
  Name:    regionName,
  Country: regionCountry,
 }
 return f
}

func (f *fluentServiceProfileBuilder) WithPriority(priority int) loadBuilder {
 f.profile.Priority = priority
 return f
}

func (f *fluentServiceProfileBuilder) WithLoad(load int) endBuilder {
 f.profile.Load = load
 return f
}

func (f *fluentServiceProfileBuilder) Build() *ServiceProfile {
 return f.profile
}

// 关键点6: 定义一个实例化Builder对象的工厂方法
func NewFluentServiceProfileBuilder() idBuilder {
 return &fluentServiceProfileBuilder{profile: &ServiceProfile{}}
}

实现 Fluent API 模式有 6 个关键点,大部分与传统的建造者模式类似:

  1. 为 ServiceProfile 定义一个 Builder 对象 fluentServiceProfileBuilder
  2. 把需要构建的 ServiceProfile 设计为 Builder 对象 fluentServiceProfileBuilder 的成员属性。
  3. 定义一系列构建属性的 Fluent 接口,通过方法的返回值控制属性的构建顺序,这是实现 Fluent API 的关键。比如 WithId 方法的返回值是 typeBuilder 类型,表示紧随其后的就是 WithType 方法。
  4. 定义一个 Fluent 接口(这里是 endBuilder)返回完成构建的 ServiceProfile,在最后调用链的最后调用。
  5. 为 Builder 定义一系列构建方法,也即实现关键点 3 中定义的 Fluent 接口,并在构建方法中返回 Builder 对象指针本身。
  6. 定义一个实例化 Builder 对象的工厂方法 NewFluentServiceProfileBuilder(),返回第一个 Fluent 接口,这里是 idBuilder,表示首先构建的是 Id 属性。

Fluent API 的使用与传统的建造者实现使用类似,但是它限定了方法调用的顺序。如果顺序不对,在编译期就报错了,这样就能提前把问题暴露在编译器,减少了不必要的错误使用。

// Fluent API的使用方法
profile := NewFluentServiceProfileBuilder().
 WithId("service1").
 WithType("order").
 WithStatus(Normal).
 WithEndpoint("192.168.0.1"8080).
 WithRegion("region1""beijing""China").
 WithPriority(1).
 WithLoad(100).
 Build()

// 如果方法调用不按照预定的顺序,编译器就会报错
profile := NewFluentServiceProfileBuilder().
 WithType("order").
 WithId("service1").
 WithStatus(Normal).
 WithEndpoint("192.168.0.1"8080).
 WithRegion("region1""beijing""China").
 WithPriority(1).
 WithLoad(100).
 Build()
// 上述代码片段把WithType和WithId的调用顺序调换了,编译器会报如下错误
// NewFluentServiceProfileBuilder().WithType undefined (type idBuilder has no field or method WithType)

典型应用场景

建造者模式主要应用在实例化复杂对象的场景,常见的有:

  • 配置对象。比如创建 HTTP Server 时需要多个配置项,这种场景通过 Functional Options 模式就能够很优雅地实现配置功能。
  • SQL 语句对象。一些 ORM 框架在构造 SQL 语句时也经常会用到 Builder 模式。比如 xorm 框架中构建一个 SQL 对象是这样的:builder.Insert().Into("table1").Select().From("table2").ToBoundSQL()
  • 复杂的 DTO 对象
  • ......

优缺点

优点

1、将复杂的构建逻辑从业务逻辑中分离出来,遵循了单一职责原则
2、可以将复杂对象的构建过程拆分成多个步骤,提升了代码的可读性,并且可以控制属性构建的顺序。
3、对于有多种构建方式的场景,可以将 Builder 设计为一个接口来提升可扩展性
4、Go 语言中,利用 Functional Options 模式可以更为简洁优雅地完成复杂对象的构建。

缺点

1、传统的建造者模式需要新增一个 Builder 对象来完成对象的构造,Fluent API 模式下甚至还要额外增加多个 Fluent 接口,一定程度上让代码更加复杂了。

与其他模式的关联

抽象工厂模式和建造者模式类似,两者都是用来构建复杂的对象,但前者的侧重点是构建对象/产品族,后者的侧重点是对象的分步构建过程

参考

[1] 【Go实现】实践GoF的23种设计模式:SOLID原则, 元闰子

[2] Design Patterns, Chapter 3. Creational Patterns, GoF

[3] GO 编程模式:FUNCTIONAL OPTIONS, 酷壳 CoolShell

[4] Fluent API: Practice and Theory, Ori Roth

[5] XORM BUILDER, xorm

[6] 生成器模式, refactoringguru.cn

更多文章请关注微信公众号:元闰子的邀请


评论
  • 在测试XTS时会遇到修改产品属性、SElinux权限、等一些内容,修改源码再编译很费时。今天为大家介绍一个便捷的方法,让OpenHarmony通过挂载镜像来修改镜像内容!触觉智能Purple Pi OH鸿蒙开发板演示。搭载了瑞芯微RK3566四核处理器,树莓派卡片电脑设计,支持开源鸿蒙OpenHarmony3.2-5.0系统,适合鸿蒙开发入门学习。挂载镜像首先,将要修改内容的镜像传入虚拟机当中,并创建一个要挂载镜像的文件夹,如下图:之后通过挂载命令将system.img镜像挂载到sys
    Industio_触觉智能 2025-01-03 11:39 115浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 84浏览
  •     为控制片内设备并且查询其工作状态,MCU内部总是有一组特殊功能寄存器(SFR,Special Function Register)。    使用Eclipse环境调试MCU程序时,可以利用 Peripheral Registers Viewer来查看SFR。这个小工具是怎样知道某个型号的MCU有怎样的寄存器定义呢?它使用一种描述性的文本文件——SVD文件。这个文件存储在下面红色字体的路径下。    例:南京沁恒  &n
    电子知识打边炉 2025-01-04 20:04 89浏览
  • 在快速发展的能源领域,发电厂是发电的支柱,效率和安全性至关重要。在这种背景下,国产数字隔离器已成为现代化和优化发电厂运营的重要组成部分。本文探讨了这些设备在提高性能方面的重要性,同时展示了中国在生产可靠且具有成本效益的数字隔离器方面的进步。什么是数字隔离器?数字隔离器充当屏障,在电气上将系统的不同部分隔离开来,同时允许无缝数据传输。在发电厂中,它们保护敏感的控制电路免受高压尖峰的影响,确保准确的信号处理,并在恶劣条件下保持系统完整性。中国国产数字隔离器经历了重大创新,在许多方面达到甚至超过了全球
    克里雅半导体科技 2025-01-03 16:10 122浏览
  • 光耦合器,也称为光隔离器,是一种利用光在两个隔离电路之间传输电信号的组件。在医疗领域,确保患者安全和设备可靠性至关重要。在众多有助于医疗设备安全性和效率的组件中,光耦合器起着至关重要的作用。这些紧凑型设备经常被忽视,但对于隔离高压和防止敏感医疗设备中的电气危害却是必不可少的。本文深入探讨了光耦合器的功能、其在医疗应用中的重要性以及其实际使用示例。什么是光耦合器?它通常由以下部分组成:LED(发光二极管):将电信号转换为光。光电探测器(例如光电晶体管):检测光并将其转换回电信号。这种布置确保输入和
    腾恩科技-彭工 2025-01-03 16:27 171浏览
  • 车身域是指负责管理和控制汽车车身相关功能的一个功能域,在汽车域控系统中起着至关重要的作用。它涵盖了车门、车窗、车灯、雨刮器等各种与车身相关的功能模块。与汽车电子电气架构升级相一致,车身域发展亦可以划分为三个阶段,功能集成愈加丰富:第一阶段为分布式架构:对应BCM车身控制模块,包含灯光、雨刮、门窗等传统车身控制功能。第二阶段为域集中架构:对应BDC/CEM域控制器,在BCM基础上集成网关、PEPS等。第三阶段为SOA理念下的中央集中架构:VIU/ZCU区域控制器,在BDC/CEM基础上集成VCU、
    北汇信息 2025-01-03 16:01 193浏览
  • 随着市场需求不断的变化,各行各业对CPU的要求越来越高,特别是近几年流行的 AIOT,为了有更好的用户体验,CPU的算力就要求更高了。今天为大家推荐由米尔基于瑞芯微RK3576处理器推出的MYC-LR3576核心板及开发板。关于RK3576处理器国产CPU,是这些年的骄傲,华为手机全国产化,国人一片呼声,再也不用卡脖子了。RK3576处理器,就是一款由国产是厂商瑞芯微,今年第二季推出的全新通用型的高性能SOC芯片,这款CPU到底有多么的高性能,下面看看它的几个特性:8核心6 TOPS超强算力双千
    米尔电子嵌入式 2025-01-03 17:04 49浏览
  • 自动化已成为现代制造业的基石,而驱动隔离器作为关键组件,在提升效率、精度和可靠性方面起到了不可或缺的作用。随着工业技术不断革新,驱动隔离器正助力自动化生产设备适应新兴趋势,并推动行业未来的发展。本文将探讨自动化的核心趋势及驱动隔离器在其中的重要角色。自动化领域的新兴趋势智能工厂的崛起智能工厂已成为自动化生产的新标杆。通过结合物联网(IoT)、人工智能(AI)和机器学习(ML),智能工厂实现了实时监控和动态决策。驱动隔离器在其中至关重要,它确保了传感器、执行器和控制单元之间的信号完整性,同时提供高
    腾恩科技-彭工 2025-01-03 16:28 169浏览
  • PLC组态方式主要有三种,每种都有其独特的特点和适用场景。下面来简单说说: 1. 硬件组态   定义:硬件组态指的是选择适合的PLC型号、I/O模块、通信模块等硬件组件,并按照实际需求进行连接和配置。    灵活性:这种方式允许用户根据项目需求自由搭配硬件组件,具有较高的灵活性。    成本:可能需要额外的硬件购买成本,适用于对系统性能和扩展性有较高要求的场合。 2. 软件组态   定义:软件组态主要是通过PLC
    丙丁先生 2025-01-06 09:23 71浏览
  • 物联网(IoT)的快速发展彻底改变了从智能家居到工业自动化等各个行业。由于物联网系统需要高效、可靠且紧凑的组件来处理众多传感器、执行器和通信设备,国产固态继电器(SSR)已成为满足中国这些需求的关键解决方案。本文探讨了国产SSR如何满足物联网应用的需求,重点介绍了它们的优势、技术能力以及在现实场景中的应用。了解物联网中的固态继电器固态继电器是一种电子开关设备,它使用半导体而不是机械触点来控制负载。与传统的机械继电器不同,固态继电器具有以下优势:快速切换:确保精确快速的响应,这对于实时物联网系统至
    克里雅半导体科技 2025-01-03 16:11 181浏览
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 102浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 89浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 75浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 121浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 100浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦