Java链式编程与Builder(建造者)设计模式

一、链式编程

1.1.释义 

        链式编程,也叫级联式编程,调用对象的函数时返回一个this对象指向对象本身,达到链式效果,可以级联调用。 

1.2.特点 

        可以通过一个方法调用多个方法,将多个方法调用链接起来,形成一条“链式”,从而提高代码的可读性。 

 1.2.原理

        链式编程的原理是返回一个this对象,也就是返回对象本身,从而达到链式效果。 

1.3.优点 

        编程性强、代码简洁 、可读性强。

1.4.使用条件 

        方法返回当前对象,即返回this;或方法支持链式调用,即返回调用该方法的对象。 

1.4.1.使用示例 

import lombok.Data;

/**
 * 要实现链式编程,我们需要让setParam1()和setParam2()都返回this。
 * 当手写set方法时,无需 @Data注解
 * 在此仅为了使用 @Data的toString()
 */
@Data
public class Sample {

    private String param1;
    private String param2;
    private String param3;

    public Sample setParam1(String param1) {
        this.param1 = param1;
        return this;
    }
    public Sample setParam2(String param2) {
        this.param2 = param2;
        return this;
    }
    public Sample setParam3(String param3) {
        this.param3 = param3;
        return this;
    }
}

 1.4.2.示例输出

二、String链式示例

2.1.源码 

         例如可以将某对象toString()转化为String后,或将String对象valueOf()赋值后,进行concat()拼接、replace()替换、substring()截取。符合的方法很多,大多数都能组装起来,使之符合链式编程。

三、StringBuffer和StringBuilder链式示例

3.1.源码 

3.2.使用示例 

        同时,Collection接口下的List的stream流,也是使用的链式编程,这里不做介绍。 

四、@Accessors注解开启链式编程 

4.1.源码 

@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface Accessors {
	/**
	 * If true, accessors will be named after the field and not include a {@code get} or {@code set}
	 * prefix. If true and {@code chain} is omitted, {@code chain} defaults to {@code true}.
	 * <strong>default: false</strong>
	 * 
	 * @return Whether or not to make fluent methods (named {@code fieldName()}, not for example {@code setFieldName}).
	 */
	boolean fluent() default false;
	
	/**
	 * If true, setters return {@code this} instead of {@code void}.
     * 如果是true,setters方法返回{this} 而不是{void}
     * 
	 * <strong>default: false</strong>, unless {@code fluent=true}, then <strong>default: true</strong>
	 * 
	 * @return Whether or not setters should return themselves (chaining) or {@code void} (no chaining).
	 */
	boolean chain() default false;
	
	/**
	 * If present, only fields with any of the stated prefixes are given the getter/setter treatment.
	 * Note that a prefix only counts if the next character is NOT a lowercase character or the last
	 * letter of the prefix is not a letter (for instance an underscore). If multiple fields
	 * all turn into the same name when the prefix is stripped, an error will be generated.
	 * 
	 * @return If you are in the habit of prefixing your fields (for example, you name them {@code fFieldName}, specify such prefixes here).
	 */
	String[] prefix() default {};
}

 4.2.注解使用

@Data
@Accessors(chain = true)
public class Sample {

    private String param1;
    private String param2;
    private String param3;

}

        上述代码是对1.4.1中的示例代码进行的简化,可以看出,当使用注解时,不用自己再设计具体的链式实现,注解会开启链式操作。这个注解常用在Spring中的实体类上。 

        同时,使用@Accessors(fluent = true)时,省略给对象赋值和取值时候得set、get前缀,可以直接用对象点出来元素,不用set。 

 4.3.测试

 五、使用Builder模式实现Java链式编程

        Builder模式是一种对象创建模式,允许我们创建一个对象,并设置其属性值。示例的Builder模式实现如下所示:        

public class Sample {

    private String name;
    private String gender;
    private String age;

    private Sample(){}
    public static SampleBuilder builder() {
        return new SampleBuilder();
    }

    public static class SampleBuilder {

        private Sample sample = new Sample();

        public SampleBuilder setName(String name) {
            sample.name = name;
            return this;
        }

        public SampleBuilder setGender(String gender) {
            sample.gender = gender;
            return this;
        }
        public SampleBuilder setAge(String age) {
            sample.age = age;
            return this;
        }

        public Sample build() {
            return sample;
        }
    }
}

        在上面的代码示例中,我们首先创建了一个Sample类。为了实现Builder模式,我们还创建了一个SampleBuilder类。SampleBuilder类中有两个with方法,分别用于设置name属性、gender属性和age属性。它们都返回SampleBuilder对象,这样就可以实现链式调用。在参数设置完成后,我们通过build方法创建Sample对象。使用Builder模式进行链式编程的示例如下:

         在上面的示例中,我们通过Sample.builder()创建了SampleBuilder对象,并使用其中的set方法设置参数。在设置完成后,我们通过build方法创建了Sample对象。

        上面这就是一个最简单的builder链式编程,简单在于,能成链能赋值,仅此而已。但如果需要取值,需要对参数校验,这个类就不够用了,需要补充更多的规定,这就抛砖引玉的引出了Java重要设计模式之一的建造者模式。

六、Builder(建造者)设计模式 

6.1.实用范围

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

        当构造过程必须允许被构造的对象有不同表示时。

 6.2.角色

        在这样的设计模式中,有以下几个角色:

        1 builder:为创建一个产品对象的各个部件指定抽象接口。

        2 ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口。

        3 Director:构造一个使用Builder接口的对象。

        4 Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

 6.3.Builder 模式创建步骤

        1)在类中,创建一个静态内部类,包含外部类的全部属性;

        2)在内部类中,为每一个属性进行赋值;

        3)内部类中创建 build 方法,返回外部类对象

        4)在外部类中创建静态 builder方法,返回内部类对象

6.4.残次品示例 

public class Sample {

    //Sample 类的属性都是不可变的。所有的属性都添加了final修饰符,在构造方法中设置了值。
    private final String name;
    private final String gender;
    private final Double age;
    //对外只提供getters方法。
    public String getName() {
        return name;
    }
    public String getGender() {
        return gender;
    }
    public Double getAge() {
        return age;
    }
    //Sample 类的构造方法是私有的。也就是说调用者不能直接创建User对象。
    private Sample(SampleBuilder builder){
        this.name = builder.name;
        this.gender = builder.gender;
        this.age = builder.age;
    }
    public static class SampleBuilder {
        private String name;
        private String gender;
        private Double age;
        public SampleBuilder SampleBuilder(){
            return new SampleBuilder();
        }

        public SampleBuilder setName(String name) {
            this.name = name;
            return this;
        }

        public SampleBuilder setGender(String gender) {
            this.gender = gender;
            return this;
        }
        public SampleBuilder setAge(Double age) {
            this.age = age;
            return this;
        }

        public Sample build() {
            //添加参数校验
            Sample sample = new Sample(this);
            if (sample.getAge() < 0 || sample.getAge() > 125){
                throw new IllegalStateException("Age out of range:" + sample.getAge());
            }
            if (!("男".equals(sample.getGender()) || "女".equals(sample.getGender()))){
                throw new IllegalStateException("Error Gender Input:" + sample.getGender());
            }
            return sample;
        }
    }
}

         可以看到,基本链式编程形成,同时参数也会进行校验,符合要求。但之所以叫残次品,是因为这只是build链式开发,但说设计模式,明显“德不配位”。

weiwan,daixu 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

若隐若现的芯片

先看效果&#xff1a; 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>若隐若现的芯片</title><script src"https://unpkg.co/gsap3/dist/gsap.min.js">…

Selenium基础 — Selenium自动化测试框架介绍

1、什么是selenium Selenium是一个用于Web应用程序测试的工具。只要在测试用例中把预期的用户行为与结果都描述出来&#xff0c;我们就得到了一个可以自动化运行的功能测试套件。Selenium测试套件直接运行在浏览器中&#xff0c;就像真正的用户在操作浏览器一样。Selenium也是…

我的创作纪念日兼GPT模型简单介绍

目录 一、引言 二、收获与开端 2.1 问题&#xff1a;在创作的过程中都有哪些收获&#xff1f; 2.2 模型开端 三、日常与深入 3.1 问题&#xff1a;当前创作和你的学习是什么样的关系&#xff1f; 3.2 模型深入介绍 3.2.1 无监督预训练 3.2.2 有监督下游任务精调 四、…

多元回归预测 | Matlab灰狼算法(GWO)优化极限梯度提升树XGBoost回归预测,GWO-XGBoost回归预测模型,多变量输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元回归预测 | Matlab灰狼算法(GWO)优化极限梯度提升树XGBoost回归预测,GWO-XGBoost回归预测模型,多变量输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源…

2023MWC精彩回顾 | 未来数字世界中的社交,游戏与娱乐

6月28日至6月30日&#xff0c;由GSMA主办的2023 MWC 上海世界移动通信大会&#xff08;简称“MWC 上海”&#xff09;启幕。「Paraverse平行云」参与组织并主持了本次大会中【未来数字世界中的社交&#xff0c;游戏与娱乐】的主题会议。 「Paraverse平行云」携手上海交通大学、…

ChatGPT 提示词设置

提示词 Prompt&#xff08;提示词&#xff09;&#xff1a;当我们询问GPT时&#xff0c;发送的消息就是Prompt。 通过给出合适的Prompt&#xff0c;可以让GPT了解我们的想法&#xff0c;在根据我们的想法做出更加合适的判断&#xff0c;帮助我们完成任务&#xff0c;提高效率。…

el-tab-pane 和el-tooltip及el-tree 组合使用

<el-tabs v-model"groupId" tab-click"handleClick"><el-tab-pane label"全部" name"0"></el-tab-pane><el-tab-pane v-for"items in editableTabs" :key"items.group_id" :name"item…

MySQL注入-SQLi-Less1笔记

前置知识点&#xff1a; 1. SELECT 1,2,3 用于查询数据通道的方式 例如Less-1中,Secury数据库中的users表结构如下&#xff0c;可以看到有散列&#xff0c;当用户在页面输入id的时候&#xff0c;会查询到对应的散列数据也就是<id>/<username>/<password>&a…

分布式监控zabbix的使用(一)

zabbix 一、添加zabbix客户端主机&#xff0c;测试是否能连接服务端和客户端都设置 hosts 解析设置 zabbix 的下载源&#xff0c;安装 zabbix-agent2修改 agent2 配置文件通过键值测试连通性在 Web 页面中添加 agent 主机 二、自定义监控内容在客户端创建自定义key 三、在web页…

Lion:闭源大语言模型的对抗蒸馏

Lion&#xff1a;闭源大语言模型的对抗蒸馏 Lion&#xff0c;由香港科技大学提出的针对闭源大语言模型的对抗蒸馏框架&#xff0c;成功将 ChatGPT 的知识转移到了参数量 7B的 LLaMA 模型&#xff08;命名为 Lion&#xff09;&#xff0c;在只有 70k训练数据的情况下&#xff0…

微服务网关技术选型:Zuul2、Gateway、OpenResty、Kong

1、简介 当使用单体应用程序架构时&#xff0c;客户端&#xff08;Web 或移动端&#xff09;通过向后端应用程序发起一次 REST 调用来获取数据。负载均衡器将请求路由给 N 个相同的应用程序实例中的一个。然后应用程序会查询各种数据库表&#xff0c;并将响应返回给客户端。微…

443端口被占用,vmware居然也来捣乱

今天搬砖时发现应用起不来了&#xff0c;显示出了熟悉的error *************************** APPLICATION FAILED TO START ***************************~~重点在这块哈 Description:Web server failed to start. Port 443 was already in use.Action:Identify and stop the p…

Modbus tcp转ETHERCAT在Modbus软件中的配置方法

Modbus tcp和ETHERCAT是两种不同的协议&#xff0c;这给工业生产带来了很大的麻烦&#xff0c;因为这两种设备之间无法通讯。但是&#xff0c;远创智控YC-ECT-TCP网关的出现&#xff0c;却为这个难题提供了解决方案。 YC-ECT-TCP网关能够连接到Modbus tcp总线和ETHERCAT总线中…

Android之WebView加载PDF链接预览PDF文件

文章目录 前言一、效果图二、实现步骤1.在项目main目录下新建一个assets2.新建一个js为index.js3.新建一个HTML为index.html4.xml布局4.Activity类&#xff08;kotlin&#xff09;5.Activity类&#xff08;Java&#xff09; 总结 前言 Android的webview压根就不支持加载pdf&am…

基于单片机的智能空调系统的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;LCD1602液晶显示当前水温&#xff0c;定时提醒&#xff0c;水量变化DS18B20检测当前水体温度&#xff1b;水位传感器检测当前水位&#xff1b;继电器驱动加热片进行水温加热&#xff1b;定时提醒喝水&#xff0c;蜂鸣器报警&#x…

详解HTTP协议和HTTPS协议

目录 一.HTTP协议 1.什么是HTTP 2.HTTP发展历史 3.HTTP请求和响应 4. 抓包的方式和工具Fiddler 1.开发者工具 2.Fiddler 二.请求和响应 1.请求和响应报文 2.URL结构 3.常见的方法 1.GET方法 2.POST方法 3.其他方法 三.请求报头(header) 1.Host 2.Content-Length 3.Co…

python自动化办公——定制化将电子签名批量签写到PDF文件

python自动化办公——定制化将电子签名批量签写到PDF文件 文章目录 python自动化办公——定制化将电子签名批量签写到PDF文件1、安装依赖2、需求分析3、代码 1、安装依赖 首先需要下载所需要的库 pip install pdf2image pip install img2pdf pip install opencv-python此外还…

vue + el-table点击表头改变其当前样式

废话不多说&#xff0c;先看效果&#xff1a; 网上找了一大圈没有符合的&#xff0c;只能自己看着搞&#xff1a; 直接贴代码&#xff1a; <el-tableref"table":data"tableData"borderstripesort-change"changeColumn"><el-table-colu…

springMVC(二)—— 进阶

一、解决中文乱码问题 解决中文乱码问题的关键在于判断字符是什么时候乱码的 先在java程序里刚生成这个值的地方打印一下&#xff0c;如果在控制台输出就乱码了&#xff0c;那就排除浏览器和jsp页面的编码出问题。否则 看浏览器的编码 看这个jsp页面的编码是否设置好了 一般不用…

简要介绍 | 两阶段点云目标检测:理论与实践

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对两阶段点云目标检测进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 两阶段点云目标检测&#xff1a;理论与实践 在这篇博客中&#xff0c;我们将探索两阶段点云目标检测的理论基础和实际应用…