源码链接(Gitee码云):https://gitee.com/oldou/javadesignpatterns
这里有我整理好的Java23种设计模式的源码以及博客教程,博客教程中介绍了Java23种设计的模式的各种实现方式以及应用场景,非常适用于学习以及提高我们的设计思维,如果对大家有所帮助,请记得star一下给予作者一定的精神支持,你的star是我写出更好的博客的动力,谢谢大家。
建造者模式也属于创建型模式,它提供了一种创建对象的最佳方式。
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
主要作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。
开发中应用场景:
例子:假如我们现在有一个计算机类Computer,其中cpu和ram是必选的参数,其他的三个是可选的参数,那么我们如何来构建这个类的实例呢?下面我们通过传统的建造者模式来实现一下:
第一步:创建我们的目标Computer类:
package com.oldou.builder.demo03;
/**
* 产品:相当于就是Product
*/
public class Computer {
private String cpu;//必须
private String ram;//必须
private int usbCount;//可选
private 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;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", ram='" + ram + '\'' +
", usbCount=" + usbCount +
", keyboard='" + keyboard + '\'' +
", display='" + display + '\'' +
'}';
}
}
第二步:创建抽象构建者类
/**
* 抽象的建造者Builder
*/
public abstract class ComputerBuilder {
public abstract void setUsbCount();
public abstract void setKeyboard();
public abstract void setDisplay();
public abstract Computer getComputer();
}
第三步:实体构建者类,我们可以根据要构建的产品种类产生多了实体构建者类,这里我们需要构建两种品牌的电脑,苹果电脑和联想电脑,所以我们生成了两个实体构建者类。
苹果电脑建造者类:
/**
* 苹果电脑的建造者
*/
public class MacComputerBuilder extends ComputerBuilder {
private Computer computer;
public MacComputerBuilder(String cpu,String ram){
computer = new Computer(cpu,ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(2);
}
@Override
public void setKeyboard() {
computer.setKeyboard("苹果键盘");
}
@Override
public void setDisplay() {
computer.setDisplay("苹果显示器");
}
@Override
public Computer getComputer() {
return computer;
}
}
联想电脑建造者类
package com.oldou.builder.demo03;
/**
* 联想电脑的建造者
*/
public class LenovoComputerBuilder extends ComputerBuilder {
private Computer computer;
public LenovoComputerBuilder(String cpu, String ram){
computer = new Computer(cpu,ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(4);
}
@Override
public void setKeyboard() {
computer.setKeyboard("联想键盘");
}
@Override
public void setDisplay() {
computer.setDisplay("联想显示器");
}
@Override
public Computer getComputer() {
return computer;
}
}
第四步:指导者类(Director):指挥电脑建造者按照以下方式建造电脑
package com.oldou.builder.demo03;
/**
* 指导者类:Director
* 负责指挥构建哪种电脑
*/
public class Director {
//指挥电脑建造者按照以下建造电脑,下面的属性可选
public void makeComputer(ComputerBuilder builder){
builder.setUsbCount();
builder.setDisplay();
builder.setKeyboard();
}
}
测试:
首先生成一个director (1),然后生成一个目标builder (2),接着使用director组装builder (3),组装完毕后使用builder创建产品实例 (4)。
public class Client {
public static void main(String[] args) {
//创建指挥者 首先生成一个director
Director director = new Director(); //1
//然后生成一个目标builder
ComputerBuilder builder = new MacComputerBuilder("I7处理器", "三星123");//2
//接着使用director组装builder
director.makeComputer(builder);//3
//组装完毕后使用builder创建产品实例
Computer computer = builder.getComputer();//4
System.out.println("苹果电脑"+computer.toString());
//建造联想电脑
ComputerBuilder lenovoBuilder = new LenovoComputerBuilder("I9处理器", "海力士333");
director.makeComputer(lenovoBuilder);
Computer lenovoComputer = lenovoBuilder.getComputer();
System.out.println("联想电脑:"+lenovoComputer.toString());
}
}
静态内部类的方式是传统builder模式的变种, 其中省略了director 这个角色,将构建算法交给了client端,其次将builder 写到了要构建的产品类里面,最后采用了链式调用。
如何实现呢?
以下就是代码的实现:
package com.oldou.builder.demo04;
/**
* 产品:电脑
*/
public class Computer {
private final String cpu;//必须
private final String ram;//必须
private final int usbCount;//可选
private final String keyboard;//可选
private final 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;
}
//构建Computer的实例并返回
public Computer build(){
return new Computer(this);
}
}
}
使用方式:在客户端使用链式调用,一步一步的把对象构建出来。
Computer computer=new Computer.Builder("因特尔","三星")
.setDisplay("三星24寸")
.setKeyboard("罗技")
.setUsbCount(2)
.build();
总结:通过静态内部类方式实现零件无序装配构造,这种方式使用更加灵活,更符合定义。内部有复杂对象的默认实现,使用时可以根据用户需求自由定义更改内容,并且无需改变具体的构造方式。就可以生产出不同复杂产品。
与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车!
本文建造者模式的代码示例部分来自知乎的作者:shusheng007 ,
原文链接:https://zhuanlan.zhihu.com/p/58093669
在学习建造者模式的时候,很多视频讲得有点难理解,所以就去看了很多文章,其中觉得这个作者的文章写得真的不错,讲得也很明白,在其基础上我自己稍作了一些总结。