原文链接:https://www.javaspecialists.eu/archive/Issue253.html
GoF Builder is simply a strategy for creating things. The intent of the Calendar.Builder is different. It hails from Effective Java and addresses the telescoping constructors problem. As you know, Java has neither default nor named parameters. Thus when Socket has two optional parameters, we will need 4 constructors:
Gof Builder(建造者模式) 是一个创建对象用的简单策略,和Calender.Builder是不一样的,它致敬了Effective Java 和解决了构造函数的伸缩问题,大家都知道,Java是没有默认参数和命名参数的,因此Socket如果有两个参数,我们就需要些4个构造方法:
Socket()
Socket(String host)
Socket(int port)
Socket(String host, int port)
Add one parameter boolean ssl and we now need 8 constructors:
如果再添加一个参数boolean ssl 那我们就需要8个构造函数了
Socket()
Socket(String host)
Socket(int port)
Socket(String host, int port)
Socket(boolean ssl)
Socket(String host, boolean ssl)
Socket(int port, boolean ssl)
Socket(String host, int port, boolean ssl)
Since Java does not have named parameters either, things get real funky when parameters are of the same type. For example, let’s add int timeout. And let’s try to make both port and timeout optional. This would result in ambiguous constructors:
自从java不能用名称来区分参数,遇到参数类型相同的时候就比较操蛋了,举个栗子,让我们添加两个方法,一个方法的参数是 int timeout ,另一个是int port,声明的结果就傻傻分不清了
Socket(int port)
Socket(int timeout)
The Effective Java Builder idiom solves this by creating an inner static class Builder, such as:
Effective Java Builder 的做法是创建一个内部的静态类Builder,如下
public class Socket {
private final int port;
private final String host;
private final boolean ssl;
private final int timeout;
private Socket(int port, String host, boolean ssl, int timeout) {
this.port = port;
this.host = host;
this.ssl = ssl;
this.timeout = timeout;
}
public static class Builder {
private int port = 0;
private String host = null;
private boolean ssl = false;
private int timeout = 0;
public Builder port(int port) {
this.port = port;
return this;
}
public Builder host(String host) {
this.host = host;
return this;
}
public Builder ssl(boolean ssl) {
this.ssl = ssl;
return this;
}
public Builder timeout(int timeout) {
this.timeout = timeout;
return this;
}
public Socket build() {
return new Socket(port, host, ssl, timeout);
}
}
}
We only need one constructor in Socket and clients can create variations of Socket with the Builder:
如果使用Builder,我们只需要一个构造函数就可以解决这个问题
Socket s1 = new Socket.Builder().port(8080).timeout(60).build();
Socket s2 = new Socket.Builder().ssl(true).build();
If Java had default and named parameters, we could write this as:
如果java有默认的命名参数,我们就可以这么写
// in the distant future, Java might be as cool as Kotlin_
public class SocketJavaX {
private final int port;
private final String host;
private final boolean ssl;
private final int timeout;
public SocketJavaX(int port=0, String host=null, boolean ssl=false, int timeout=0) {
this.port = port;
this.host = host;
this.ssl = ssl;
this.timeout = timeout;
}
}
Our client code would also be simpler:
我们的客户端代码就会更加简单
SocketJavaX s1 = new Socket(port=8080, timeout=60);
SocketJavaX s2 = new Socket(ssl=true);
The Effective Java Builder idiom would become obsolete. The idiom is a workaround for a missing language feature, rather than an OO design pattern.
如果上面成真了,Effective Java Builder 就该过时了,这种风格只是弥补了一下java的缺失,而不是一种设计模式.