Java
package builder;
public class DbPool {
private String name;
private String host;
private Integer port;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
@Override
public String toString() {
return "DbPool{" +
"name='" + name + '\'' +
", host='" + host + '\'' +
", port=" + port +
'}';
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String name;
private String host;
private Integer port;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder host(String host) {
this.host = host;
return this;
}
public Builder port(Integer port) {
this.port = port;
return this;
}
public DbPool build() {
// 增加字段校验
if (this.name == null || this.name.isEmpty()) {
throw new RuntimeException("name不能为空");
}
final DbPool dbPool = new DbPool();
dbPool.setName(this.name);
dbPool.setHost(this.host == null || this.host.isEmpty() ? "127.0.0.1" : this.host);
dbPool.setPort(this.port == null || this.port == 0 ? 8080 : this.port);
return dbPool;
}
}
}
Go
package builder
import "errors"
type DbPool struct {
Name string
Host string
Port int
}
type DbPoolBuilder struct {
name string
host string
port int
}
func (d *DbPoolBuilder) SetName(name string) *DbPoolBuilder {
d.name = name
return d
}
func (d *DbPoolBuilder) SetHost(host string) *DbPoolBuilder {
d.host = host
return d
}
func (d *DbPoolBuilder) SetPort(port int) *DbPoolBuilder {
d.port = port
return d
}
func (d *DbPoolBuilder) Build() (*DbPool, error) {
if d.name == "" {
return nil, errors.New("name不能为空")
}
var dp = DbPool{Name: d.name}
if d.host == "" {
dp.Host = "127.0.0.1"
} else {
dp.Host = d.host
}
if d.port == 0 {
dp.Port = 8080
} else {
dp.Port = d.port
}
return &dp, nil
}
为什么需要 Builder 模式?
使用构造器,参数太多的情况下,会导致代码的可读性和易用性降低。(构造器参数存在顺序,顺序出错传参就出错了。)
Java 常见使用建造者模式的方式
工作中一般直接使用 lombok 的 @Builder 注解直接生成 Builder 代码,无需写如此多的模板代码。
Go 中最常见的传参方式
package builder
import "errors"
type Option struct {
Host string
Port int
}
type OptionFunc func(option *Option)
// NewDbPool 新建DbPool
// name 必填项
// options 选填项
func NewDbPool(name string, options ...OptionFunc) (*DbPool, error) {
if name == "" {
return nil, errors.New("name不能为空")
}
defaultOption := Option{
Host: "127.0.0.1",
Port: 8080,
}
for _, optionFunc := range options {
optionFunc(&defaultOption)
}
return &DbPool{
Name: name,
Host: defaultOption.Host,
Port: defaultOption.Port,
}, nil
}
// 测试
func TestOption(t *testing.T) {
pool, err := builder.NewDbPool("option_db_pool", func(option *builder.Option) {
option.Host = "localhost"
option.Port = 1234
})
if err != nil {
t.Error(err)
}
fmt.Println(pool)
assert.Equal(t, pool.Host, "localhost")
}