博文原址:折腾Java设计模式之建造者模式
建造者模式
Separate the construction of a complex object from its representation, allowing the same construction process to create various representations.
将复杂对象的构造与其表现分离,允许相同的构造过程用来创建不同的表现。通俗点就是,一个对象创建过程很复杂,我们将其每项元素创建过程抽离出来,通过相同的构造过程可以构造出不用的对象。还不懂可以看到如下的UML图。
建造者模式UML图
此AbstractPersonBuilder
就是如上的相同的构造,而不同的表现就是此处的PersonOneBuilder
和PersonTwoBuilder
两个相同方式的构造器,但是具体的实现是不一样而构造出不同的表现。所以就是相同的构造过程而构造出不同的对象。
建造者模式角色
抽象建造者(AbstractPersonBuilder
或者Builder
):抽象类或者接口,复杂对象的属性的抽象方法,并不涉及具体的对象部件的创建;
具体建造者(PersonOneBuilder
和PersonTwoBuilder
):实现抽象建造者,针对不同的业务,具体化复杂对象的各部分的创建。 在建造过程完成后,提*品的实例;
指挥者(Director
):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建;
具体的产品(Person
):需创建的复杂对象;
建造者模式源码干货
源码地址:请点击我
在这里我分为三种情况讲讲建造者模式,第一种是我们最原始的建造者模式来构建,第二种是我们在实体对象时会使用的,第三种是我们平常对实体对象最常规使用方法借助lombok。
第一种建造者模式
使用的真是上面按照角色来建造的方式,稍微比如下的两种方法负责点。
抽象建造者
public abstract class AbstractPersonBuilder {
protected Person product = new Person();
public abstract void buildName();
public abstract void buildAge();
public abstract void buildChildren();
public Person build() {
return product;
}
}
第一个具体建造者
public class PersonOneBuilder extends AbstractPersonBuilder {
public void buildName() {
product.setName("老one");
}
public void buildAge() {
product.setAge(44);
}
public void buildChildren() {
product.setChildren(Lists.newArrayList("小one"));
}
}
第二个具体建造者
public class PersonTwoBuilder extends AbstractPersonBuilder {
public void buildName() {
product.setName("老two");
}
public void buildAge() {
product.setAge(55);
}
public void buildChildren() {
product.setChildren(Lists.newArrayList("小two"));
}
}
Person类充当产品数据
public class Person {
private String name;
private int age;
private List<String> children;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", children=" + children +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getChildren() {
return children;
}
public void setChildren(List<String> children) {
this.children = children;
}
}
指挥者,指定具体的建造者用来建造对象
public class Director {
private AbstractPersonBuilder builder;
public Director(AbstractPersonBuilder builder) {
this.builder = builder;
}
public void setBuilder(AbstractPersonBuilder builder) {
this.builder = builder;
}
public Person construct() {
builder.buildName();
builder.buildAge();
builder.buildChildren();
return builder.build();
}
}
示例
@Slf4j
public class Application {
public static void main(String[] args) {
Director director = new Director(new PersonOneBuilder());
Person person = director.construct();
log.info("person的信息:{}", person);
director.setBuilder(new PersonTwoBuilder());
person = director.construct();
log.info("person的信息:{}", person);
}
}
结果:
第二种建造者模式
第二种方式比上面那种简单些,因为我们只指定了一种构造方式,并且还可以借用第三方工具IDEA+Plugins。
在IDEA中可以搜索
使用方法:
1.找到对应需要添加bulid的类通过自动生成快捷键可以查看到build
2.根据自己的风格可以定义bulid的名字,各个bulid方法的前缀以及包名,具体bulider如下代码中。
PersonBuilder用来Person的构建者
public final class PersonBuilder {
private String name;
private int age;
private List<String> children;
private PersonBuilder() {
}
public static PersonBuilder builder() {
return new PersonBuilder();
}
public PersonBuilder withName(String name) {
this.name = name;
return this;
}
public PersonBuilder withAge(int age) {
this.age = age;
return this;
}
public PersonBuilder withChildren(List<String> children) {
this.children = children;
return this;
}
public Person build() {
Person person = new Person();
person.setName(name);
person.setAge(age);
person.setChildren(children);
return person;
}
}
Person类充当产品数据
public class Person {
private String name;
private int age;
private List<String> children;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", children=" + children +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getChildren() {
return children;
}
public void setChildren(List<String> children) {
this.children = children;
}
}
示例
@Slf4j
public class Application {
public static void main(String[] args) {
Person wang = PersonBuilder.builder()
.withAge(40)
.withName("老王")
.withChildren(Lists.newArrayList("李一一", "吴老三"))
.build();
log.info("老王的信息:{}", wang);
}
}
结果如下:
第三种建造者模式
第三种模式相对来说就简单非常多,因为我们借用的是lombok的@Builder注解。lombok在18.2版本中引入了@SuperBulider注解用来解决@Builder类的继承不生效的问题。详细的使用阔以看我上篇文章 折腾Java设计模式之模板方法模式
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private String name;
private int age;
private List<String> children;
}
@Slf4j
public class Application {
public static void main(String[] args) {
Person wang = Person.builder()
.age(40)
.name("老王")
.children(Lists.newArrayList("李一一", "吴老三"))
.build();
log.info("老王的信息:{}", wang);
}
}
结果:
总结
第二、三种模式在我们经常操作像对VO、DO、DTO对象时,常用如此定义。第一种标准的建造者模式,其实本身指挥者这个角色是不关心具体的产品实现的,相对于是一种解耦,对于如果新增一种建造者实现,可以方便扩展,符合开闭原则,但是无独有偶,实现了上述优点后,但是缺点也跟着来,新增了很多类,维护成本高,如果建造者内部发生变更,就不太适合建造者这种模式了。总体而言还是有很多使用场景的。像StringBulider其实也是一种。像之前在spring-boot的spring-cache中的扩展redis缓存的ttl和key名这篇文章中定义的RedisCacheManagerBuilder,以及我们常用的以后要讲的Feign的Builder等等。
欢迎关注
折腾Java设计模式之建造者模式的更多相关文章
-
折腾Java设计模式之备忘录模式
原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...
-
折腾Java设计模式之状态模式
原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...
-
折腾Java设计模式之模板方法模式
博客原文地址:折腾Java设计模式之模板方法模式 模板方法模式 Define the skeleton of an algorithm in an operation, deferring some ...
-
折腾Java设计模式之访问者模式
博客原文地址:折腾Java设计模式之访问者模式 访问者模式 Represent an operation to be performed on the elements of an object st ...
-
折腾Java设计模式之命令模式
博客原文地址 折腾Java设计模式之命令模式 命令模式 wiki上的描述 Encapsulate a request as an object, thereby allowing for the pa ...
-
Java 设计模式之建造者模式(四)
原文地址:Java 设计模式之建造者模式(四) 博客地址:http://www.extlight.com 一.前言 今天继续介绍 Java 设计模式中的创建型模式--建造者模式.上篇设计模式的主题为 ...
-
java设计模式3——建造者模式
java设计模式3--建造者模式 1.建造者模式介绍: 建造者模式属于创建型模式,他提供了一种创建对象得最佳方式 定义: 将一个复杂对象的构建和与它的表示分离,使得同样的构建过程可以创建不同的表示 主 ...
-
Java设计模式之建造者模式(Builder)
前言: 最近一直在学习okHttp,也对其做了一些整理,okHttp和Retrofit结合大大加速我们的开发效率,源码里面采用了很多设计模式,今天我们来学习一下其中的设计模式之一建造者模式. 建造者模 ...
-
Java设计模式之三 ----- 建造者模式和原型模式
前言 在上一篇中我们学习了工厂模式,介绍了简单工厂模式.工厂方法和抽象工厂模式.本篇则介绍设计模式中属于创建型模式的建造者模式和原型模式. 建造者模式 简介 建造者模式是属于创建型模式.建造者模式使用 ...
随机推荐
-
YYModel 源码解读(二)之NSObject+YYModel.h (1)
本篇文章主要介绍 _YYModelPropertyMeta 前边的内容 首先先解释一下前边的辅助函数和枚举变量,在写一个功能的时候,这些辅助的东西可能不是一开始就能想出来的,应该是在后续的编码过程中 ...
-
百度前端技术学院2015JavaScript基础部分实现自己的小型jQuery
// 实现一个简单的Query function $(selector) { ); if (firstChar == "#") { var len = selector.split ...
-
sqlmap遇到url重写的示例
url_rewrite 这个问题 国内外的坛子里都有人问. D:\cygwin\pentest\database\sqlmap\doc \faq.pdf 下面是官方给的解答. 1.15 How to ...
-
Java 8 Date Time API Example Tutorial – LocalDate, Instant, LocalDateTime, Parse and Format
参考 Java 8 Date and Time API is one of the most sought after change for developers. Java has been mis ...
-
Winpcap网络编程十之Winpcap实战,两台主机通过中间主机通信
注:源码等等的我不会全然公开的,此篇文章写出来为大家的网络编程或者课程设计提供一定的思路.. 好,本次我们须要完毕的任务是: 完毕两台主机通过中间主机的数据通信(网络层) 添加基于IP地址的转发功能 ...
-
js继承与闭包(笔记)
1.一切引用类型都是对象,对象时属性的集合:typeof null === 'object'(例外): 2.对象都是通过函数创建来的,比如var obj = new Object();typeof O ...
-
关于No qualifying bean of type [XXX.XXX] found for dependency 的一次记录
异常开始于spring+springmvc+mybatis 注解配置,启动tomcat服务器出现No qualifying bean of type [com.***.service] found f ...
-
【手记】解决VS发布asp.net项目报错“该项目中不存在目标GatherAllFilesToPublish”及后续问题
办法在最后. 用VS2017打开一个以前用VS2010写的asp.net项目后,设置好发布选项(发布到文件夹),发布的时候报错如图: 搜索一番,找到的办法是: 在项目文件(xxx.csproj)中,在 ...
-
SQL SERVER 字符拆分列为多行
注:先学习sql server里的递归CTE. 假设有兴趣表Hobbys Name Hobby 小张 篮球,足球,羽毛球 Name Hobby 小张 篮球 小张 足球 小张 羽毛球 采用[递归cte] ...
-
PHP如何获取本周周二的日期?
在计算某个特定周几的时候,需要对当前时间做一个转换和比对,比如,如何求出本周周二的时间日期. 代码如下: <?php // 如何计算本周的星期二 $time=time();//时间 $now=d ...