设计模式(四)建造者模式 Builder
- Builder:
《Effective Java》 第2条:遇到多个构造器参数时要考虑用构建器。
建造者模式(Builder Pattern),也称生成器模式,定义如下:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Separate the construction of a complex object from its representation so that the same construction process can create different representation.
- 什么时候使用 Builder:
我们常常会看见这种情况:我需要一个初始化一个复杂对象,在初始化的同时完成参数的赋值工作。
- 数据模型:
@Data
@EqualsAndHashCode
@ToString
public class PolicyCommon { private String code;
private String category;
private String name;
private String inceptionDate; public PolicyCommon() {
super();
} public PolicyCommon(String code, String category, String name) {
super();
this.code = code;
this.category = category;
this.name = name;
}
}
- 模型分析:
PolicyCommon 带有4个参数,假定只有 inceptionDate不需要在创建的时候赋值。
剩余3个参数参与初始化的工作,那么这个对象初始化之后的状态可能性为:2^3=8。
- 传统的解决方案1——使用无参构造器,然后依次调用 set() 方法:
@Test
void testPolicyCommon1() {
PolicyCommon policy = new PolicyCommon();
policy.setName("Gerrard");
policy.setCode("11123768");
policy.setCategory("Engineer");
System.out.println(policy);
}
这种方法,将构造对象的过程拆分成多个动作,是存在风险的。
因为对象不是一次性构造完成,使得对象在构造过程中存在状态不一致的情况。
期间有 this 指针溢出的风险,阻碍了这个对象称为不可变对象的可能。在多线程条件下,需要额外的工作才能保证线程安全。
- 传统的解决方案2——使用重叠参数的构造器:
@Test
void testPolicyCommon2() {
PolicyCommon policy = new PolicyCommon("11123768", "Engineer", "Gerrard");
System.out.println(policy);
}
这样做的劣势在于:
- 从调用者的角度来说,属性的意义不明显,很容易将参数位置颠倒了,但是编译器并没有报错,例如: new PolicyCommon("Engineer", "Gerrard", "11123768");
- 如果我只想初始化一个属性,如 code,那么构造器的调用会有许多冗余参数。例如:new PolicyCommon("11123768", null, null);
- Builder 给出的解决方案:
使用一个静态内部类 Builder,Builder 持有需要动态生成的属性。
Builder 为每一个属性,提供 set() 方法,但是与通常的set() 方法不同,这些 set() 方法的返回值是 Builder 本身。
Builder 提供一个 build() 方法,返回类型为外部类。
外部类中,提供一个参数为 Builder 对象的构造器,且将其的权限设置为 private,如此一来,构造器的唯一途径就是 build() 方法。
- 代码:
@Data
@EqualsAndHashCode
@ToString
public class PolicyBuilder { private String code;
private String category;
private String name;
private String inceptionDate; private PolicyBuilder(Builder builder) {
code = builder.code;
category = builder.category;
name = builder.name;
} public static class Builder { private String code;
private String category;
private String name; public Builder setCode(String code) {
this.code = code;
return this;
} public Builder setCategory(String category) {
this.category = category;
return this;
} public Builder setName(String name) {
this.name = name;
return this;
} public PolicyBuilder build() {
return new PolicyBuilder(this);
}
}
}
- 调用 Builder:
@Test
void testPolicyBuilder() {
PolicyBuilder policy = new PolicyBuilder.Builder().setName("Gerrard").setCode("11123768").build();
System.out.println(policy);
}
可以看出,Builder 初始化的过程中,对参数选择更加自由,而且它不会使对象处于不同的状态。
劣势在于冗长的内部类代码,以及构建过程中会增加一个 Builder 对象。
- 使用 Lombok 一键 Builder:
细心的朋友,在最初的 PolicyCommon 的数据模型中,会发现三个注解,这是 Lombok 框架的功能(org.projectlombok,License = MIT)。
@Data,为类的每一个属性,自动生成 get() 和 set() 方法。
@EqualsAndHashCode,为类生成 equals() 和 hashCode() 方法。
@ToString,为类生成 toString() 方法。
除此之外,Lombok 还提供了 @Builder 的注解,自动为类提供了 Builder 的功能。
- Lombok Builder:
@Data
@EqualsAndHashCode
@ToString
public class PolicyBuilderLombok { private String code;
private String category;
private String name;
private String inceptionDate; @Builder
public PolicyBuilderLombok(String code, String category, String name) {
super();
this.code = code;
this.category = category;
this.name = name;
}
}
@Test
void testPolicyBuilderLombok() {
PolicyBuilderLombok policy = new PolicyBuilderLombok.PolicyBuilderLombokBuilder()
.name("Gerrard").code("11123768").build();
System.out.println(policy);
}
- 解析 @Builder:
检查元注解:@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
这表明这个注解可以加在:类、构造器、方法(不推荐加在方法上)。
@Builder 加在类上 <==> ,在类的全参构造器上加上 @Builder。
@Builder 加在构造器上,这个构造器的入参就是内部类 Builder 的动态参数。
设计模式(四)建造者模式 Builder的更多相关文章
- 乐在其中设计模式(C#) - 建造者模式(Builder Pattern)
原文:乐在其中设计模式(C#) - 建造者模式(Builder Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 建造者模式(Builder Pattern) 作者:webabc ...
- 二十四种设计模式:建造者模式(Builder Pattern)
建造者模式(Builder Pattern) 介绍将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 示例用同样的构建过程创建Sql和Xml的Insert()方法和Get()方 ...
- 【设计模式】建造者模式 Builder Pattern
前面学习了简单工厂模式,工厂方法模式以及抽象工厂模式,这些都是创建类的对象所使用的一些常用的方法和套路, 那么如果我们创建一个很复杂的对象可上面的三种方法都不太适合,那么“专业的事交给专业人去做”,2 ...
- 设计模式之建造者模式——Builder
一.概述 Builder模式,中文名为建造者模式,又名生成器模式.构建者模式等,是创建型设计模式之一.用于将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 1.适用性: 对象 ...
- Python 设计模式之建造者模式 Builder Pattern
#引入建造者模式 肯德基的菜单上有 薯条, 鸡腿,鸡翅,鸡米花,可乐,橙汁,火腿汉堡,至尊虾汉堡,牛肉汉堡 , 鸡肉卷等这些单品,也有很多套餐. 比如 套餐1:鸡翅,至尊虾汉堡,可乐,薯条 套餐2:鸡 ...
- 设计模式-05建造者模式(Builder Pattern)
1.模式动机 比如我们要组装一台电脑,都知道电脑是由 CPU.主板.内存.硬盘.显卡.机箱.显示器.键盘和鼠标组成,其中非常重要的一点就是这些硬件都是可以灵活选择,但是组装步骤都是大同小异(可以组一个 ...
- 设计模式之建造者模式(Builder)
建造者模式原理:建造模式主要是用于产生对象的各个组成部分,而抽象工厂模式则用于产生一系列对象,建造者模式而且要求这些对象的组成部分有序. 代码如下: #include <iostream> ...
- 设计模式之建造者模式Builder(创建型)
1. 概述 在软件开发的过程中,当遇到一个“复杂的对象”的创建工作,该对象由一定各个部分的子对象用一定的算法构成,由于需求的变化,复杂对象的各个部分经常面临剧烈的变化,但将它们组合在一起的算法相对稳定 ...
- 【UE4 设计模式】建造者模式 Builder Pattern
概述 描述 建造者模式,又称生成器模式.是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无需知道复杂 ...
- 创建型设计模式之建造者模式(Builder)
结构 意图 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 适用性 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时. 当构造过程必须允许被构造的对象有不 ...
随机推荐
- 2015 ACM/ICPC Asia Regional Changchun Online Pro 1008 Elven Postman (BIT,dfs)
Elven Postman Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)T ...
- 字符串的驻留(String Interning)
http://www.cnblogs.com/artech/archive/2007/03/04/663728.html 关于字符串的驻留的机制,对于那些了解它的人肯定会认为很简单,但是我相信会有很大 ...
- ajax的序列化表单提交
通过传统的 form 表单提交的方式上传文件 ? 1 2 3 4 <form id="uploadForm" action="" method=" ...
- 【上下界网络流】bzoj2502: 清理雪道
模型:无源汇有上下界可行流 LJN:模板题吧 Description 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的 ...
- asp发送短信验证码 pst方式
<script language="jscript" runat="server"> Array.prototype.get = function ...
- Tcl/Cmds
- verilog $fopen 函数的小缺陷
system task $fopen 的argument 为1.文件名字(可以包含具体的文件路径但是注意用)2.打开方式比如"r"."w"."a&qu ...
- Linux 用户管理(二)
一.groupadd --create a new group 创建新用户 -g --gid GID 二.groupdel --delete a group 三.passwd --update us ...
- FSMC原理通俗解释
所以不用GPIO口直接驱动液晶,是因为这种方法速度太慢,而FSMC是用来外接各种存储芯片的,所以其数据通信速度是比普通GPIO口要快得多的.TFT-LCD 驱动芯片的读写时序和SRAM的差不多,所以就 ...
- 图上两点之间的第k最短路径的长度 ACM-ICPC 2018 沈阳赛区网络预赛 D. Made In Heaven
131072K One day in the jail, F·F invites Jolyne Kujo (JOJO in brief) to play tennis with her. Howe ...