Kotlin~生成器模式

news2025/1/5 8:48:07

介绍

主要作用

逐步构造复杂对象,该对象的属性更多的扩展属性,如Glide的使用。

组成

UML

  • Builder:提供逐步创建产品的步骤

  • Director:创建可复用的特定产品(规定Builder规定一系列的步骤创建产品,非必须)

  • Product:具体的产品类(可能包含了相同的父类或接口)

kt中实现方案

Kt中可以简化该模式的使用,下面介绍常见写法

1. 使用具名可选参数

class Computer(
    val mainboard: String, // 主板
    val cpu: String, // 处理器
    val ram: String, // 内存
    val battery: String, // 电源
    val gpu: String? = null, // 显卡
    val hardDisk: String? = null, // 硬盘
    val networkInterface: String? = null, // 网线接口
    val cdDriver: String? = null, // 光驱
    val os: String? = null, // 系统
    val chassis: String? = null, // 机箱
    val mouse: String? = null, // 鼠标
    val keyboard: String? = null, // 键盘
    val monitor: String? = null // 显示器
)

fun main() {
    // 具名参数
    val computer = Computer(
        "超微X8QB6-F", "Intel Xeon E7-8870", "海盗船(CORSAIR) 复仇者LPX DDR4 2133 64GB 7000", "西门子豪华供电柜",
        gpu = "Leadtek/丽台Quadro Plex 7000",
        os = "Windows 11",
        mouse = "RAPOO雷柏 3710 2.4G激光无线鼠标",
        keyboard = "Optimus Maximus 多功能 概念式键盘",
        monitor = "Sharp/夏普 LB-1085 108英寸 FULL HD专业液晶显示器"
    )
}

具名函数的优点:

  • 代码简洁优雅,无论是 Product 的类结构,或者是创建一个 Product 实例
  • 创建 Product 实例时,显式指定参数名即可,无须按顺序传入
  • 所有参数均使用 val 声明,相比 Builder 中使用 var 更加安全

2. 使用apply,also作用域函数

class Car {
    var color: String = ""
    var doors: Int = 0
    var wheel: String = ""
    override fun toString(): String {
        return "Car(color='$color', doors=$doors, wheel='$wheel')"
    }
}

fun main() {
    val car = Car().apply {
        color = "Red"
        doors = 4
        wheel = "Good"
    }
    println(car)
}

3. 标准写法

我们这里使用带接收器的Lambda表达式。

class Car1(
    val model: String? = null,
    val year: Int = 0
) {
    private constructor(builder: Builder) : this(
        builder.model,
        builder.year
    )

    class Builder {
        var model: String? = null
        var year: Int = -1

        fun build() = Car1(this)
    }

    companion object {
        /**
         * 带接收者的函数类型,这意味着我们需要向函数传递一个Builder类型的实例
         */
        inline fun build(block: Builder.() -> Unit) = Builder().apply(block).build()
    }

    override fun toString(): String {
        return "Car1(model=$model, year=$year)"
    }
}

fun main() {
    val car2 = Car1.build {
        model = "名字"
        year = 2017
    }
    println(car2)
}

4. 结合lambda DSL优雅写法弹框示例

import androidx.annotation.StringRes

class Dialog1 {
    var title: String = ""
    var content: String = ""

    // 内敛函数结合lambda
    inline fun show(func: Dialog1.() -> Unit) {
        this.func()
        this.show()
    }

    fun show() {
        println("title:$title,content:$content")
    }
}

class Dialog2 {
    var title: String = ""
    var content: String = ""

    fun title(@StringRes res: Int? = null, text: CharSequence? = null): Dialog2 {
        text?.let {
            title = it.toString()
        }
        return this
    }

    fun content(@StringRes res: Int? = null, text: CharSequence? = null): Dialog2 {
        text?.let {
            content = it.toString()
        }
        return this
    }

    inline fun show(func: Dialog2.() -> Unit) {
        this.func()
        this.show()
    }

    fun show() {
        println("title:$title,content:$content")
    }
}

class Dialog private constructor(
    val title: String,
    val text: String?,
    val onAccept: (() -> Unit)?
) {
    class Builder(val title: String) {
        var text: String? = null
        var onAccept: (() -> Unit)? = null
        fun setText(text: String?): Builder {
            this.text = text
            return this
        }

        fun setOnAccept(onAccept: (() -> Unit)?): Builder {
            this.onAccept = onAccept
            return this
        }

        fun build() = Dialog(title, text, onAccept)
    }
}

fun main() {
    Dialog1().show {
        title = "标题"
        content = "内容"
    }

    Dialog2().show {
        title(text = "标题")
        content(text = "内容")
    }

    val dialog1 = Dialog.Builder("Some title")
        .setText("Great dialog")
        .setOnAccept { println("I was clicked") }
        .build()
    val dialog2 = Dialog.Builder("Another dialog")
        .setText("I have no buttons")
        .build()
    val dialog3 = Dialog.Builder("Dialog with just a title").build()
}

总结

应用场景

盖房子,定制汽车

优点

  • 分步创建更加灵活
  • 可以复用相同的制作代码
  • 严格遵循单一职责原则

缺点
代码整体复杂度增加

生成器模式就是为了构建复杂对象,创建对象的方式是多步骤的。关于建造模式的变种写法参考(Java 大白话讲解设计模式之 – 建造者(Builder)模式 - 简书)

参考:

Kotlin 自带的Builder建造者模式

Kotlin设计模式-Builder模式 - 简书

秒懂设计模式之建造者模式(Builder pattern)

给人看的Kotlin设计模式——构造者模式

Kotlin - 改良构建者模式 - 掘金

你会用Kotlin实现构建者模式吗?

Kotlin - 改良构建者模式 - 掘金

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

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

相关文章

21新版FL Studio水果电音编曲Daw宿主软件好不好用?

首先是FL Studio(以下简称FL)的逻辑和其它宿主软件都不太一样,FL的逻辑就与众不同。FL的逻辑也可以分为三部分:通道机架、混音台和播放列表。在Live里每个发送轨都可以插入一个乐器以及若干个效果器。你有200个发送轨,…

vcenter 起不来报错VMware ESX 找不到虚拟磁盘“vCenter Server 7.0U3_12.vmdk”。请确认路径有效并重试

针对无快照时丢失.vmdk描述符文件:基础磁盘文件为-flat.vmdk是存在的 那个可以进行恢复操作步骤如下1.确定 flat.vmdk基础磁盘文件的大小(字节)2.创建与flat.vmdk相同大小的新的空虚拟磁盘。3.重命名新创建的.vmdk磁盘的描述符文件匹配原始虚…

如何运行一个py项目

在pycharm中打开项目文件确保安装python环境此时是使用python3.7版本,没有的话需要添加环境:add interpreter在anaconda(安装参考https://blog.csdn.net/m0_67357141/article/details/123633490)中选择基础环境(base&a…

Python中的列表

1.创建列表 使用中括号把要添加的元素括起来,不同元素用逗号隔开。 >>> rhyme [1, 2, 3, 4, 5, "上山打老虎"] >>> print(rhyme) [1, 2, 3, 4, 5, 上山打老虎]2.访问列表中的元素 (1)希望顺序访问列表中的元…

博弈论入门

分类 要素 常见博弈 完全信息静态博弈 纳什均衡 囚徒困境 古诺双寡头模型 古诺双寡头模型的条件 市场中有且仅有两家公司策略为同质商品的量,qiq_iqi​边际成本为c,生产成本就为c*q,在这里我们的边际成本是常数。需求曲线:Pa−b∗…

2009-01-从学校毕业步入社会

在一间坐满学生的教室中,台上同学正在对自己毕业答辩项目进行介绍,台下第一排坐着打分的老师,这群人正在进行计算机专业的毕业答辩,台下人群中一个叫刘文轩的同学紧张又期盼的看着前面正在进行答辩的同学,看着同学们优…

react中useReduer和useEffect

相信很多人对于变成中reduce、reducer命名都存在困惑,为了更好理解useRedecuer,我们不妨先来说说reduce。 如何理解reduce和reducer reduce:函数式编程当中的一个术语,reduce操作被称为Fold折叠 // 通过reduce,数组…

公司内部有奖知识答题活动怎么做

公司年会趣味问答、员工业务知识考核、消防安全、党史等知识测试......公司内部的答题活动已经成了众多管理者、HR日常工作中一部分。如何让组织者更轻松、更公平公正地举办答题活动?如何让员工更积极参与呢?试试答题小博士的有奖答题。有奖答题活动形式…

中晶FileScan 3222扫描仪 Code:-206,卡纸或滚筒出错

中晶FileScan 3222是中晶品牌下的一款扫描仪。 型号 3222 产品类型 平板式+馈纸式 扫描光源 LED

机器人中的数值优化之BFGS(convex and smooth)

本文ppt来自深蓝学院《机器人中的数值优化》 目录 1 Why Quasi-Newton Methods 2 Rate of convergence 3 Quasi-Newton Methods 3.1 Quasi-Newton approximation 3.2 preserve descent direction 3.3 secant condition 3.4 iterate B 3.5 Parsed solution B 4 Cont…

微信小程序学习第2天——模板语法与样式,全局配置与页面配置

文章目录一、WXML模板语法1、数据绑定2、事件绑定3、条件渲染4、列表渲染二、WXSS模板样式rpximport语法导入样式全局和局部样式三、全局配置全局配置文件及常用配置项windowtabBar四、页面配置一、WXML模板语法 1、数据绑定 数据绑定的原则:①在data中定义数据 ②…

亚信安慧携AntDB数据库入选信通院软件供应链厂商和产品名录

日前,中国信息通讯研究院(简称:中国信通院)在其主办的3SCON软件供应链安全大会上,发布了软件供应链厂商和产品名录。中国信通院云计算与大数据研究所副所长栗蔚表示,我国软件供应链安全发展面临制度体系待完…

微服务组件(高并发带来的问题 服务器雪崩效应 Sentinel入门)

高并发带来的问题 服务器雪崩效应 Sentinel入门高并发带来的问题模拟高并发服务器雪崩效应常见容错方案Sentinel入门(常见的容错组件)什么是Sentinel?订单服务集成Sentinel流控规则预热流控等待流控关联流控链路流控降级(提供一个兜底方案)慢调用比例异常比例异常数案例高并发…

显著图(Saliency map)

这里写目录标题概念应用算法传统算法静态显著性算法:对数光谱(SpectralResidual):静态显著性算法:细粒方法(FineGrained):人工智能算法基于眼动仪预测显著性区域方法积分梯度方法对比…

jsp学生宿舍管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp 学生宿舍管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql,使…

【Vue】Vue的简介和特性

一、Vue简介Vue.js可以说是MVVM架构的最佳实践,是一个JavaScript MVVM库,是一套构建用户界面的渐进式前端框架。专注于MVVM中的ViewModel,不仅做到了数据双向绑定,而且也是一款相对比较轻量级的JS 库,API简洁。1. 构建…

Day 15 SpringBoot Condition

1 Condition作用:该功能可以选择性的创建Bean1.1 验证在Spring的IOC容器中有一个User的 Bean,现要求导入Jedis坐标后,加载该Bean,没导入,则不加载。【第一步】创建User对象Repository Conditional(ClassCondition.clas…

【yolov5系列】yolov5-onnxruntime在Ubuntu和RK芯片上运行

前言 这里yolov5的onnx模型的推理,分别在 x64上 和 移动端上运行,前者在自己本地Ubuntu系统上运行,后者在瑞芯微的rk3566上运行。 要完成如上工作我们需要一下步骤: 1 下载onnxruntime编译好的库2 下载opencv库并安装3 下载交叉编…

88E1548P大流量传输插拔网线导致网络不通

1、测试环境硬件:NXP LS1046A ARM64平台 88E1548P 软件:linux 4.19.26 linux 5.10.35环境说明:88E1548P 是一个QSGMII 的 phy 芯片,LS1046A CPU 提供4个GMAC 与 88E1548P 连接,就是4个千兆网口。2、具体现象eth7发包…

OFDM系统架构梳理(1)

1、ofdm简介OFDM是一种特殊的多载波传输方案,它可以被看作是一种调制技术,也可以被当作一种复用技术。多载波传输把数据流分解成若干子比特流,这样每个子数据流将具有低得多的比特速率,用这样的低比特率形成的低速率多状态符号再去…