设计模式 - 建造者模式

概述

建造者(builder)模式,也是我们常见的一种模式,有没有想过我们什么时候适合使用建造者模式呢?
从我们周围世界来说,如果我们想“建造”一辆汽车,我们可以手工一点点地去建造,也可以选择将“建造”汽车分为几个部分,比如建造轮子,建造底盘,建造架子,建造发动机等等,然后再组装在一起,从我们的感知上来说,显然分部分建造更符合我们的认知,因为这样很容易形成标准,给人感觉也更清晰。
同时,在软件中,我们构造一个复杂对象也是一样的道理,我们期待能够一步一步地方便我们的创建。这特别适合那种成员特别多,而且部分是required的,部分是optional的对象的构造。

实现

现在比如有一个用户User类,包含网站登陆用户的信息,我们需要的刻画信息有:

public class User {
    private String uid;      // required,用户id
    private String name;     // required,用户名
    private String address;  // optional,用户地址
    private int age;         // optional,用户年龄
    private String phone;    // optional,用户手机号
}

上述User类有两个必须的属性,三个可选属性,如果让你构造一个实例,你会怎么构造呢。大部分,我们会选择用构造函数或者setter和getter属性来处理我们元素的值。那如果我们希望类的元素是final的,即不可变的,用什么方式来处理呢。
显而易见,setter和getter方式是我们最常用的,但是如果希望这个被建造的类初始化后不再修改,或者能够控制参数,就可以考虑下建造者模式了,直接实现示例如下:

public class User {
    private final String uid;      // required,用户id
    private final String name;     // required,用户名
    private final String address;  // optional,用户地址
    private final int age;         // optional,用户年龄
    private final String phone;    // optional,用户手机号

    // User类只提供getter方法,此处省略

    private User(UserBuilder builder) {
        this.uid = builder.uid;
        this.name = builder.name;
        this.address = builder.address;
        this.phone = builder.phone;
        this.age = builder.age;
    }

    public static class UserBuilder {
        private final String uid;
        private final String name;
        private String address = "";
        private int age = -1;
        private String phone = "";

        public UserBuilder(String uid, String name) {
            this.uid = uid;
            this.name = name;
        }
        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }
        public UserBuilder address(String address) {
            this.address = address;
            return this;
        }
        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }
        public User build() {
            return new User(this);
        }
    }

    public static void main(String[] args) {
        User user = new UserBuilder("111", "jack")
                .address("china")
                .age(20)
                .build();
    }
}

再举一个例子,比如,有一个接收查询请求的服务,我们构造查询条件,返回响应信息,查询条件是:

public class QueryCondition {
    private String query_word;      // required,查询词
    private String ip;              // optional,查询来源地址
    private String caller;          // optional,查询方
    private List<String> ret_fields;// optional,查询返回的数据字段
}

我们该如何设计一个建造者模式来构造该查询条件呢,示例如下:

public class QueryCondition {
    private final String query_word;      // optional,查询词
    private final String ip;              // optional,查询来源地址
    private final String caller;          // optional,查询方
    private final List<String> ret_fields;// optional,查询返回的数据字段

    public String getQuery_word() {
        return query_word;
    }
    public String getIp() {
        return ip;
    }
    public String getCaller() {
        return caller;
    }
    public List<String> getRet_fields() {
        return ret_fields;
    }

    public QueryCondition(String query_word, String ip, String caller, List<String> ret_fields) {
        this.caller = caller;
        this.query_word = query_word;
        this.ip = ip;
        this.ret_fields = ret_fields;
    }
}
public class QueryConditionBuilder {
    private String query_word = "";      // required,查询词
    private String ip = "";              // optional,查询来源地址
    private String caller = "default";          // optional,查询方
    private List<String> ret_fields = new ArrayList<String>();// optional,查询返回的数据字段

    private QueryConditionBuilder() { }

    public static QueryConditionBuilder createBuilder() {
        return new QueryConditionBuilder();
    }

    public QueryConditionBuilder setQueryWord(String query_word) throws Exception {
        if (query_word == null) {
            throw new Exception("query word is null");
        }
        this.query_word = query_word;
        return this;
    }
    public QueryConditionBuilder setIp(String ip) {
        this.ip = ip;
        return this;
    }
    public QueryConditionBuilder setCaller(String caller) {
        this.caller = caller;
        return this;
    }
    public QueryConditionBuilder setRetFields(List<String> ret_fields) throws Exception {
        if (ret_fields == null || ret_fields.isEmpty()) {
            throw new Exception("qeury ret field error");
        }
        this.ret_fields = ret_fields;
        return this;
    }
    public QueryCondition build() {
        return new QueryCondition(query_word, ip, caller, ret_fields);
    }
}

我们可以看到,通过建造者模式,我们还可以对构造对象的参数进行统一管理和限制,避免未完整初始化的对象被使用。
以上就是建造者模式,其实也很简单,对不对。


【参考资料】建造者模式实践
【参考资料】建造者模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值