前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【设计模式】1分钟给你整明白什么是Builder建造者模式

【设计模式】1分钟给你整明白什么是Builder建造者模式

作者头像
行百里er
发布2020-12-02 14:41:06
3460
发布2020-12-02 14:41:06
举报
文章被收录于专栏:JavaJourneyJavaJourney

场景切入

我们常常能碰到一个对象有非常多属性的时候,比如一个雇员信息,包括姓名,年龄,性别,住址,级别,身高,体重,身份证号,社保福利,绩效...等等字段,有时候我们需要得到部分字段的信息,也有可能需要获取全部字段信息,如果一个字段一个字段的set,那是相当繁琐的!!!

代码解决

针对如上情况,该怎么简化如此繁琐的工作呢?别急,builder模式来帮忙!

直接上代码看效果:

代码语言:javascript
复制
public class Employee {
    private String name;
    private Integer age;
    private String sex;
    private Integer height;
    private Integer weight;
    private String address;
    private String level;
    //...还有很多属性

    //私有的构造方法
    private Employee(){

    }

    public static class EmployeeBuilder{
        Employee employee = new Employee();

        public EmployeeBuilder basicInfo(String name, Integer age, String sex){
            employee.name = name;
            employee.age = age;
            employee.sex = sex;
            return this;
        }

        public EmployeeBuilder height(Integer height){
            employee.height = height;
            return this;
        }

        public EmployeeBuilder weight(Integer weight){
            employee.weight = weight;
            return this;
        }

        public EmployeeBuilder address(String address){
            employee.address = address;
            return this;
        }

        public EmployeeBuilder level(String level){
            employee.level = level;
            return this;
        }

        public Employee build(){
            return employee;
        }
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", height=" + height +
                ", weight=" + weight +
                ", address='" + address + '\'' +
                ", level='" + level + '\'' +
                '}';
    }
}

我在Employee类中定义了一个静态内部类EmployeeBuilder,负责将Employee字段拆分,静态内部类每个方法都负责给相应的字段赋值,最后定义一个build方法来返回我们需要的Employee对象。

来看调用:

代码语言:javascript
复制
public static void main(String[] args) {
    Employee e = new Employee.EmployeeBuilder()
            .basicInfo("张三", 18, "男")
            .height(178)
            .weight(65)
            //.level("初级")
            .build();
    System.out.println(e);
}

需要构造什么字段,直接在new Employee.EmployeeBuilder()后面.什么方法就行了,这是经典的链式编程的方式,每个方法返回对象本身就可以实现。

builder模式

本例中代码实现就使用了builder的设计模式,通过builder模式我们很容易就能构造像Employee这样很复杂的对象。

builder设计模式就是用来构造复杂对象的,其特点:

  • 分离复杂对象的构建和表示
  • 同样的构建过程可以创建不同的表示

其实,我们在工作中自然而然的就会使用这种模式,我们无须对模式的概念啊,定义啊进行特别的记忆,用的时候自然实用,水到渠成。

比如,

代码语言:javascript
复制
StringBuilder sb = new StringBuilder();
sb.append("下蛋公鸡").append(",").append("公鸡中的战斗鸡!");
System.out.println(sb.toString());

还有StringBuffer也可以这样用,我们来看一下源码:

StringBuilder

代码语言:javascript
复制
public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{

    //...略

    //append()方法返回对象本身,这样在append一次之后还能接着直接.append()的方式调用。
    //这其实就是建造者模式的体现,可以一部分一部分的建造对象,根据实际需要来调用append
    @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
    //...
}

StringBuffer

代码语言:javascript
复制
public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
    //...

    //方法和StringBuilder的append实现方式是一样的(他们都继承了AbstractStringBuilder类),只不过方法加了synchronized关键字,是线程安全的。
    @Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    //...
}

他们的父类AbstractStringBuilder

代码语言:javascript
复制
abstract class AbstractStringBuilder implements Appendable, CharSequence {
    //...
    
    public AbstractStringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
    
    //...
}

StringBuilder&StringBuffer

这也是建造者模式的体现。

大名鼎鼎的Mybatis的SqlSessionFactoryBuilder就使用了builder模式

MyBatis的SqlSessionFactoryBuilder

这一堆的build方法返回都是SqlSessionFactory,调用不同的方法,可以构建出不同特性的SqlSessionFactory。

小结

  • 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式
  • 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适
  • 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式

无需记忆,自然使用。

看完点赞,养成习惯。举手之劳,赞有余香。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 行百里er 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 场景切入
  • 代码解决
  • builder模式
  • 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档