【Java开发】设计模式 03:建造者模式
创始人
2024-06-01 23:03:22
0

1 建造者模式介绍

建造者模式使用多个简单的对象一步一步构建成一个复杂的对象。

当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。

📌 场景

当一个类的构造函数参数超过4个,而且这些参数有些是可选的时,我们通常有两种办法来构建它的对象。 例如我们现在有如下一个类计算机类Computer,其中cpu与ram是必填参数,而其他3个是可选参数,那么我们如何构造这个类的实例呢,通常有两种常用的方式:

public class Computer {private String cpu;//必须private String ram;//必须private int usbCount;//可选private String keyboard;//可选private String display;//可选
}

① 折叠构造函数模式

public class Computer {private String cpu;//必须private String ram;//必须private int usbCount;//可选,默认为0private String keyboard;//可选,默认为罗技键盘private String display;//可选,默认为三星显示器public Computer(String cpu, String ram) {this(cpu, ram, 0);}public Computer(String cpu, String ram, int usbCount) {this(cpu, ram, usbCount, "罗技键盘");}public Computer(String cpu, String ram, int usbCount, String keyboard) {this(cpu, ram, usbCount, keyboard, "三星显示器");}public Computer(String cpu, String ram, int usbCount, String keyboard, String display) {this.cpu = cpu;this.ram = ram;this.usbCount = usbCount;this.keyboard = keyboard;this.display = display;}
}

② Javabean模式

public class Computer {private String cpu;//必须private String ram;//必须private int usbCount;//可选private String keyboard;//可选private String display;//可选public String getCpu() {return cpu;}public void setCpu(String cpu) {this.cpu = cpu;}public String getRam() {return ram;}public void setRam(String ram) {this.ram = ram;}public int getUsbCount() {return usbCount;}
...
}

这也可用lombok依赖包的@Data注解替代~

📌 两种方式的弊端

第一种使用和阅读不方便,当使用该类的构造函数时,需要搞清楚各参数的含义,而且还是按照严格的顺序。

第二种由于类的属性是分布设置的,那么构建过程中对象的状态容易发生变化,容易出错。

那么builder模式可以较好地解决以上问题!

2 构建者模式实现

📌 步骤

  1. 在Computer 中创建一个静态内部类 Builder,然后将Computer 中的参数都复制到Builder类中。

  1. 在Computer中创建一个private的构造函数,参数为Builder类型

  1. 在Builder中创建一个public的构造函数,参数为Computer中必填的那些参数,cpu 和ram。

  1. 在Builder中创建设置函数,对Computer中那些可选参数进行赋值,返回值为Builder类型的实例

  1. 在Builder中创建一个build()方法,在其中构建Computer的实例并返回

也可直接使用lombok依赖包的@Builder注解一键解决。

📌 具体代码

public class Computer {private String cpu;//必须private String ram;//必须private int usbCount;//可选,默认为0private String keyboard;//可选,默认为罗技键盘private String display;//可选,默认为三星显示器private Computer(Builder builder){this.cpu=builder.cpu;this.ram=builder.ram;this.usbCount=builder.usbCount;this.keyboard=builder.keyboard;this.display=builder.display;}public static class Builder{private String cpu;//必须private String ram;//必须private int usbCount;//可选private String keyboard;//可选private String display;//可选public Builder(String cup,String ram){this.cpu=cup;this.ram=ram;}public Builder setUsbCount(int usbCount) {this.usbCount = usbCount;return this;}public Builder setKeyboard(String keyboard) {this.keyboard = keyboard;return this;}public Builder setDisplay(String display) {this.display = display;return this;}public Computer build(){return new Computer(this);}}
}

📌 使用

Computer computer = new Computer.Builder("AMD","小米").setUsbCount(0).setKeyboard("罗技").setDisplay("三星24寸").build();

📌 @Builder注解一键解决

@Builder
public class Computer {private String cpu;//可选private String ram;//可选private int usbCount;//可选private String keyboard;//可选private String display;//可选
}class test{public static void main(String[] args) {Computer computer = Computer.builder().cpu("AMD").ram("金士顿").usbCount(0).keyboard("罗技").display("三星24寸").build();}
}

使用方式稍微不一样~

3 传统建造者模式

上面的内容是Builder在Java中一种简化的使用方式,经典的Builder 模式与其有一定的不同,如UML图:

📌 各角色

  • Product: 最终要生成的对象,例如 Computer实例。

  • Builder: 构建者的抽象基类(有时会使用接口代替)。其定义了构建Product的抽象步骤,其实体类需要实现这些步骤。其会包含一个用来返回最终产品的方法Product getProduct(),例如 ComputerBuilder抽象类。

  • ConcreteBuilder: Builder的实现类,如LenovoComputerBuilder类和MacComputerBuilder类。

  • Director: 决定如何构建最终产品的算法, 其会包含一个负责组装的方法void Construct(Builder builder), 在这个方法中通过调用builder的方法,就可以设置builder,例如 ComputerDirector类。

等设置完成后,就可以通过builder的 getProduct() 方法获得最终的产品。

📌 1.目标Computer类

public class Computer {private String cpu;//必须private String ram;//必须private int usbCount;//可选,默认为0private String keyboard;//可选,默认为罗技键盘private String display;//可选,默认为三星显示器public Computer(String cpu, String ram) {this.cpu = cpu;this.ram = ram;}public void setUsbCount(int usbCount) {this.usbCount = usbCount;}public void setKeyboard(String keyboard) {this.keyboard = keyboard;}public void setDisplay(String display) {this.display = display;}@Overridepublic String toString() {return "Computer{" +"cpu='" + cpu + '\'' +", ram='" + ram + '\'' +", usbCount=" + usbCount +", keyboard='" + keyboard + '\'' +", display='" + display + '\'' +'}';}
}

📌 2.抽象构建者类

public abstract class ComputerBuilder {public abstract void setUsbCount();public abstract void setKeyboard();public abstract void setDisplay();public abstract Computer getComputer();
}

📌 3.实体构建者类

public class LenovoComputerBuilder extends ComputerBuilder{private Computer computer;public LenovoComputerBuilder(String cpu, String ram) {computer=new Computer(cpu,ram);}@Overridepublic void setUsbCount() {computer.setUsbCount(4);}@Overridepublic void setKeyboard() {computer.setKeyboard("联想键盘");}@Overridepublic void setDisplay() {computer.setDisplay("联想显示器");}@Overridepublic Computer getComputer() {return computer;}
}
public class MacComputerBuilder extends ComputerBuilder{private Computer computer;public MacComputerBuilder(String cpu, String ram) {computer = new Computer(cpu, ram);}@Overridepublic void setUsbCount() {computer.setUsbCount(2);}@Overridepublic void setKeyboard() {computer.setKeyboard("苹果键盘");}@Overridepublic void setDisplay() {computer.setDisplay("苹果显示器");}@Overridepublic Computer getComputer() {return computer;}
}

📌 4.指导者类(Director)

public class ComputerDirector {public void makeComputer(ComputerBuilder builder){builder.setUsbCount();builder.setDisplay();builder.setKeyboard();}
}

📌 5.使用

首先生成一个director,然后生成一个目标builder ,接着使用director组装builder,组装完毕后使用builder创建产品实例。

    ComputerDirector director = new ComputerDirector();//1ComputerBuilder macBuilder = new MacComputerBuilder("I5处理器","三星125");//2director.makeComputer(macBuilder);//3Computer macComputer=macBuilder.getComputer();//4System.out.println("mac computer:"+macComputer.toString());ComputerBuilder lenovoBuilder=new LenovoComputerBuilder("I7处理器","海力士222");director.makeComputer(lenovoBuilder);Computer lenovoComputer=lenovoBuilder.getComputer();System.out.println("lenovo computer:"+lenovoComputer.toString());

📌 总结

其实之前用的是的变种, 首先其省略了director 这个角色,将构建算法交给了client端,其次将builder 写到了要构建的产品类里面,最后采用了链式调用。

秒懂设计模式之建造者模式(Builder pattern) - 知乎 (zhihu.com)

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...