前言
我们在使用Retrofit等这些第三方框架的时候,发现他们的使用都很方便,比如Retrofit retrofit = new Retrofit.Builder().build(),和我们通常直接new一个对象不同,他是交给Builder类,通过build()函数来构造一个Retrofit对象。
刚开始使用,可能不太明白,明明可以直接new出来,为什么要交给Builder来构造呢?那么通过学习了构造者设计模式,才明白,原来当使用者构造对象时,构造函数的参数一般大于等于五个,就可以考虑使用构造者设计模式,这样编写代码的好处,在于结构清晰,也易于扩展。
在实际工作中,我们可能接触了很多这种链式创建对象的场景,比如AlertDialog,发现这种代码在使用的时候,真的很香,不仅实现了参数传递的灵活性,也避免了因参数过多造成的混乱。总之,除了使用官方封装的这些类以外,自己在实现代码的同时,也想要动手实现一个建造者设计模式。
实现
下面我们以电脑为例,创建一个抽象类Computer,我们想想,电脑都有什么属性,品牌,型号,操作系统,用途,类型,名字等等。这些属性如果都用构造方法实现的话,会很长,而且也不易于扩展,不够灵活。
static class Computer{
String name;
String brand;
String os;
String display;
String type;
String use;
public void setName(String name) {
this.name = name;
}
public void setBrand(String brand) {
this.brand = brand;
}
public void setOs(String os) {
this.os = os;
}
public void setDisplay(String display) {
this.display = display;
}
public void setType(String type) {
this.type = type;
}
public void setUse(String use) {
this.use = use;
}
}
比如,我们需要创造一个macbook笔记本,用传统思维,直接创造一个类,然后继承Computer,通过构造函数的方法重载,完成各种需求的笔记本。这样一套下来,代码臃肿不说,也不宜与后期的维护,如果有新的属性,又要重载一个构造函数,比较繁琐。
static class MacBook extends Computer{
public MacBook() {
}
// ……
//各种构造函数
// ……
@Override
public String toString() {
return "MacBook{" +
"name='" + name + '\'' +
", brand='" + brand + '\'' +
", os='" + os + '\'' +
", display='" + display + '\'' +
", type='" + type + '\'' +
", use='" + use + '\'' +
'}';
}
}
如果有一个专门的类,来创建不同需求的笔记本,这个问题就能很好的解决。
那么这个专门的类就是Builder类,通过构造者设计模式进行优化,我们这里具体到了MacBook笔记本,在实际开发工作中,这个可以使用泛型T代替,更加灵活。
static abstract class Builder {
abstract MacBookBuilder builderName(String name);
abstract MacBookBuilder builderBrand(String brand);
abstract MacBookBuilder builderOs(String os);
abstract MacBookBuilder builderType(String type);
abstract MacBookBuilder builderUse(String use);
abstract MacBookBuilder builderDisPlay(String display);
abstract Computer build();
}
接下来,我们将利用MacBookBuilder 来构造笔记本,代码如下:
static class MacBookBuilder extends Builder{
MacBook macBook = new MacBook();
@Override
MacBookBuilder builderName(String name) {
macBook.name = name;
return this;
}
@Override
MacBookBuilder builderBrand(String brand) {
macBook.brand = brand;
return this;
}
@Override
MacBookBuilder builderOs(String os) {
macBook.os = os;
return this;
}
@Override
MacBookBuilder builderType(String type) {
macBook.type = type;
return this;
}
@Override
MacBookBuilder builderUse(String use) {
macBook.use = use;
return this;
}
@Override
MacBookBuilder builderDisPlay(String display) {
macBook.display = display;
return this;
}
@Override
Computer build() {
return macBook;
}
}
好了,我们通过测试类,测试一下,附上完整代码:
package com.example.lib;
public class BuilderTest {
public static void main(String[] args) {
Computer macbook = new MacBookBuilder()
.builderName("macbook 2023")
.builderOs("mac/os")
.builderBrand("apple")
.builderType("Laptops")
.builderDisPlay("Retina显示器")
.builderUse("studyProgram")
.build();
System.out.println(macbook.toString());
}
static class Computer{
String name;
String brand;
String os;
String display;
String type;
String use;
public void setName(String name) {
this.name = name;
}
public void setBrand(String brand) {
this.brand = brand;
}
public void setOs(String os) {
this.os = os;
}
public void setDisplay(String display) {
this.display = display;
}
public void setType(String type) {
this.type = type;
}
public void setUse(String use) {
this.use = use;
}
}
static class MacBook extends Computer{
public MacBook() {
}
@Override
public String toString() {
return "MacBook{" +
"name='" + name + '\'' +
", brand='" + brand + '\'' +
", os='" + os + '\'' +
", display='" + display + '\'' +
", type='" + type + '\'' +
", use='" + use + '\'' +
'}';
}
}
static abstract class Builder {
abstract MacBookBuilder builderName(String name);
abstract MacBookBuilder builderBrand(String brand);
abstract MacBookBuilder builderOs(String os);
abstract MacBookBuilder builderType(String type);
abstract MacBookBuilder builderUse(String use);
abstract MacBookBuilder builderDisPlay(String display);
abstract Computer build();
}
static class MacBookBuilder extends Builder{
MacBook macBook = new MacBook();
@Override
MacBookBuilder builderName(String name) {
macBook.name = name;
return this;
}
@Override
MacBookBuilder builderBrand(String brand) {
macBook.brand = brand;
return this;
}
@Override
MacBookBuilder builderOs(String os) {
macBook.os = os;
return this;
}
@Override
MacBookBuilder builderType(String type) {
macBook.type = type;
return this;
}
@Override
MacBookBuilder builderUse(String use) {
macBook.use = use;
return this;
}
@Override
MacBookBuilder builderDisPlay(String display) {
macBook.display = display;
return this;
}
@Override
Computer build() {
return macBook;
}
}
}
总结
构造者设计模式,在安卓开放当中非常常见,也是一种创建型设计模式,类似与工厂模式,但不同于工厂模式。主要优点如下:
- 客户端不需要理解产品的内部细节,完成了产品本身与产品创建的解耦
- 每一个具体的建造者都相对独立,产品的创建更加的精细化
- 增加新的具体建造者,无需修改原有的代码,符合开闭原则
- 使用链式编程,代码上更加美观