前言
我们在使用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() {}// ……//各种构造函数// …… @Overridepublic 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();@OverrideMacBookBuilder builderName(String name) {macBook.name = name;return this;}@OverrideMacBookBuilder builderBrand(String brand) {macBook.brand = brand;return this;}@OverrideMacBookBuilder builderOs(String os) {macBook.os = os;return this;}@OverrideMacBookBuilder builderType(String type) {macBook.type = type;return this;}@OverrideMacBookBuilder builderUse(String use) {macBook.use = use;return this;}@OverrideMacBookBuilder builderDisPlay(String display) {macBook.display = display;return this;}@OverrideComputer 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() {}@Overridepublic 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();@OverrideMacBookBuilder builderName(String name) {macBook.name = name;return this;}@OverrideMacBookBuilder builderBrand(String brand) {macBook.brand = brand;return this;}@OverrideMacBookBuilder builderOs(String os) {macBook.os = os;return this;}@OverrideMacBookBuilder builderType(String type) {macBook.type = type;return this;}@OverrideMacBookBuilder builderUse(String use) {macBook.use = use;return this;}@OverrideMacBookBuilder builderDisPlay(String display) {macBook.display = display;return this;}@OverrideComputer build() {return macBook;}}
}
总结
构造者设计模式,在安卓开放当中非常常见,也是一种创建型设计模式,类似与工厂模式,但不同于工厂模式。主要优点如下:
- 客户端不需要理解产品的内部细节,完成了产品本身与产品创建的解耦
- 每一个具体的建造者都相对独立,产品的创建更加的精细化
- 增加新的具体建造者,无需修改原有的代码,符合开闭原则
- 使用链式编程,代码上更加美观