Builder模式

Builder模式作为创建型模式之一,几乎随处可见,尤其是创建复杂对象时;每当构造方法不能再愉快地工作时,可能就需要它出马拯救即将”崩坏““丑化”的代码。

模式概况

  • 实际需求
    • 想创建的目标对象所需参数较多,且很多参数可能需要赋予默认值时
    • 想创建的目标对象所需参数并不需要固定的顺序时
    • 想以多种方式创建不同属性的目标对象却又不想使用多个构造方法时
    • 想创建的目标对象有可选参数时
  • 解决方案
    • 分离构建操作,使参数”可变“
  • 详细设计
    • 传入方法类似于settter,不过是由第三方传入并产生真正的对象,在此之前对象应无法进行调用

builder模式在Python中其实并无用武之地,因为Python本身提供了参数赋值较为灵活的语法,可以自由指定参数,而Java的语法已经规定只有最后一个参数可以写成可变长参数,这也大大限制了构造方法的多变性。

比如Python可以这样写构造方法:

class Point:
    def __init__(self, x=0, y=0, z=0, desc="complete point"):
        self.x = x
        self.y = y
        self.z = z
        self.desc = desc

    def display(self):
        print(self.x, self.y, self.z, self.desc)


p1 = Point(1, 2)
p1.display()

p2 = Point(y=2, z=3)
p2.display()

p3 = Point(x=1, desc="x axis")
p3.display()

输出分别为:

1 2 0 complete point
0 2 3 complete point
1 0 0 x axis

而这种写法在Java中几乎只能在注解中出现,但那无济于事;

@Documented
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Caution {
    String value1() default "m";

    int value2() default 10;

    String value3();
}

Java中也有可变长参数,但限制太多,一是只能有一个可变长参数且必须在方法末尾;二是这个参数类型必须是固定的;
var1

所以Java想实现类似效果,还得靠设计;简而言之,就是不再使用构造方法一次性将所有参数赋值,而是化整为零地对参数进行赋值。

这个过程就像实现生活中的产品组装,比如汽车,比如电脑,各零配件的选配组合成型,全程总是由第三方的一个组装者完成操作,所以叫作Builder模式。

模式实现

实际使用当中往往直接使用Builder自由组装,将整个模式精简为一个类,产品、组装者一起存在:

public class Point {

	private int x;
	private int y;
	private int z;
	private String desc;

	private Point(Builder builder){
        x = builder.x;
        y = builder.y;
        z = builder.z;
        desc = builder.desc;
	}

	public static class Builder{
		private int x = 0;
		private int y = 0;
		private int z = 0;
		private String desc = "nice";

		public Builder setX(int x){
			this.x = x;
			return this;
		}

		public Builder setY(int y){
			this.y = y;
			return this;
		}

		public Builder setZ(int z){
			this.z = z;
			return this;
		}

		public Builder setDesc(String desd){
			this.desc = desd;
			return this;
		}

		public Point build(){
			return new Point(this);
		}
	}
}

使用是这样的:

public class Main {

	public static void main(String[] args) {
        Point point = new Point.Builder()
				.setX(1)
				.setY(2)
				.setDesc("Haha")
				.build();
        System.out.println(point);
	}
}

这种精简的Builder模式,整体就是突出精简与自由;

传统的Builder模式,有三个重要角色,分别为产品、组装者、监工;
首先是产品, 也可以根据实际情况再抽象出一层抽象产品类并继承,这里产品零件(参数)较少,不再提及:

public class Point {

	private int x;
	private int y;
	private int z;
	private String desc;

	public void setX(int x) {
		this.x = x;
	}

	public void setY(int y) {
		this.y = y;
	}

	public void setZ(int z) {
		this.z = z;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	@Override
	public String toString() {
		return "Point{" +
				"x=" + x +
				", y=" + y +
				", z=" + z +
				", desc='" + desc + '\'' +
				'}';
	}
}

再者是组装者Builder,同样可以抽象出一层,这里同样因为组装流程较少不提及:

public class PointBuilder {

	private Point point = new Point();

	public void buildX(int x) {
        point.setX(x);
	}

	public void buildY(int y) {
        point.setY(y);
	}

	public void buildZ(int z) {
        point.setZ(z);
	}

	public void buildDesc(String desc) {
        point.setDesc(desc);
	}

	public Point create() {
		return point;
	}
	
}

最后是监工,也是组装者工作的地方:

public class PointDirector {
	private PointBuilder mBuilder;

	public PointDirector(PointBuilder builder) {
		this.mBuilder = builder;
	}

	public void work() {
        mBuilder.buildX(2);
        mBuilder.buildX(3);
        mBuilder.buildZ(4);
        mBuilder.buildDesc("nice");
	}
}

具体使用:

public class Main {

	public static void main(String[] args) {
        PointBuilder builder = new PointBuilder();
        PointDirector director = new PointDirector(builder);
        director.work();
        
        System.out.println(builder.create());
	}
}

用表表示出来是:

说明
Point产品/对象
PointBuilder组装者
PointDirector监工,组装者工作之地
Main最终需要调用产品/对象的地方

图表示出来是:
var2

可以看到,传统的写法步骤较多,角色也相对复杂,不如精简模式来得巧妙简洁;但传统写法有利于对Builder模式的原生理解,因此也需要有所掌握。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中builder模式是一种创建对象的设计模式,它通过将对象的构建步骤分离出来,使得构建过程更加灵活和可控。 在builder模式中,我们通常会定义一个Builder类,用于构建对象的各个属性,并最终返回一个完整的对象。具体实现方式包括: 1. 定义一个内部静态类Builder,用于构建对象。 2. 在Builder类中定义与目标对象相同的属性,并提供对应的setter方法。 3. 在Builder类中定义一个build()方法,用于将Builder对象转换为目标对象。 4. 在目标对象的构造函数中,接收Builder对象作为参数,并将Builder对象中的属性赋值给目标对象。 通过这种方式,我们可以通过链式调用Builder对象的setter方法灵活地设置对象的属性,并最终创建出完整的对象。 例如,我们可以使用builder模式来构建一个Person对象: ```java public class Person { private String name; private int age; private String gender; private Person(Builder builder) { this.name = builder.name; this.age = builder.age; this.gender = builder.gender; } public static class Builder { private String name; private int age; private String gender; public Builder setName(String name) { this.name = name; return this; } public Builder setAge(int age) { this.age = age; return this; } public Builder setGender(String gender) { this.gender = gender; return this; } public Person build() { return new Person(this); } } } ``` 使用方式如下: ```java Person person = new Person.Builder() .setName("张三") .setAge(23) .setGender("男") .build(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值