项目知识点整理——设计模式部分


Java中的Builder模式

作为一只小白,在看到下面这样额的代码时,还真是一脸懵逼。。。

 new IncomingGarmentStatBuilder()
                        .id(UUID.randomUUID())
                        .endDateInRange(toDate)
                        .range(DAILY)
                        .org(organization)
                        .value(sumValueByOrg(dailyOnceStats, organization))
                        .build()

虽然可以猜到是在创建新对象,但是这种方式还真是诡异呢🤔


什么鬼?

再加上当这段代码混在java 8 的stream处理过程中时,像下面这样,

 List<IncomingGarmentStat> dailyStats = organizations.stream()
                .map(organization ->
                new IncomingGarmentStatBuilder()
                        .id(UUID.randomUUID())
                        .endDateInRange(toDate)
                        .range(DAILY)
                        .org(organization)
                        .value(sumValueByOrg(dailyOnceStats, organization))
                        .build())
                .collect(Collectors.toList());

不学无术的我更难以理解这一堆方法调用是在干什么了。。。

这是在干嘛?

不过没有关系,看不懂这一堆方法调用,可以一个一个来。
可以从对我而言比较奇怪的这个Builder类的构造方法入手,点进去看看就好了。
这不看还好,一看真是吓一跳。这个Builder类长成了这个样子:

public class IncomingGarmentStatBuilder {
    private IncomingGarmentStat incomingGarmentStat;

    public IncomingGarmentStatBuilder() {
        incomingGarmentStat = new IncomingGarmentStat();
    }

    public IncomingGarmentStatBuilder(IncomingGarmentStat incomingGarmentStat) {
        this.incomingGarmentStat = incomingGarmentStat;
    }

    public IncomingGarmentStat build() {
        return incomingGarmentStat;
    }

    public IncomingGarmentStatBuilder id(UUID id) {
        incomingGarmentStat.setId(id);
        return this;
    }

    public IncomingGarmentStatBuilder range(StatisticRange range) {
        incomingGarmentStat.setRange(range);
        return this;
    }
....
}

可以看出,这个Builder类是对所构造的类的set方法在此进行了一次封装,使得可以通过调用与属性名相同的方法名为当前所构建的对象set属性值。
那么问题来了,当我在创建一个实体类,一般也就是一个Java Bean时,都会设计这个类的get、set方法,并通过这些方法给所要创建的对象赋值。
简单来说,例如对于一个People类而言,

public class People {
  
   private int id;
   private String name;
   private int age;
   private String gender;

  public People() {
  }

  public People(int id, String name, int age, String gender) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.gender = gender;
  }

  public setId(int id) {
    this.id = id;
  }

  public getId() {
    return id;
  }

  public setName(String name) {
    this.name = name;
  }

  public getName() {
    return name;
  }
  
  public setAge(int age) {
    this.age = age;
  }

  public getAge() {
    return age;
  }

  public setGender(String gender) {
    this.gender = gender;
  }

  public getGender() {
    return gender;
  }
}

一般都长成上面这样。按照这种大众化的People类的设计方式,我去创建一个新的People对象时,可以有两种方法:

  • 直接调用构造方法,把给定的参数通过构造方法传入,如下:
    People person = new People(9527, "华安", 24, "男");
  • 通过新建一个空对象使用set方法完成对象构建,如下:
People person = new People();
person.setId(9527);
person.setName("华安");
person.setAge(24);
person.setGender("男");

这两种方法也是我常用的方法。其实对于上述例子中的People,因为属性较少,我们通过上述的两种方式去创建实例对象都还较为方便易懂。但可以设想一下,若对于一个含有多种属性的复杂类而言,使用这种构造器传参或者使用set方法完成初始化实例对象的工作会带来什么问题?

  1. 对于通过构造器传参创建新对象,在参数较多的情况下,会使得传入参数和其对应的参数含义分离,对于读代码的人而言,不会一下就能明白这些参数的意义何在。
  2. 对于set方法传参而言,显而易见的是在大量属性需要set的情况下,需要调用多种的set方法,从而使得在构建一个对象的过程中,使得代码过于冗长。

因此,Builder类的采用,也就是建造者模式可以再保证代码可读性的前提下,使对象的创建变得灵活、简洁。对于上述的People类,采用建造者模式后,其PeopleBuilder类设计如下:

public class PeopleBuilder {
  private People person;
  
  public PeopleBuilder() {
    person = new People();
  }

  public PeopleBuilder(People person) {
    this.person = person; 
  }

  public PeopleBuilder id(int id) {
    person.setId(id);
    return this;
  }

   public PeopleBuilder name(String name) {
    person.setName(name);
    return this; 
  }

  public PersonBuilder age(int age) {
    person.setAge(age);
    return this;
  }

  public PersonBuilder gender(String gender) {
    person.setGender(gender);
    return this;
  }

  public People build() {
    return person;
  }
}

如此一来,如果要创建一个People对象,就可以用如下方式:

People person = new PeopleBuilder().id(9527)
                                   .name("华安")
                                   .age(24)
                                   .gender("男")
                                   .build();

如此一来相比之前的set方法就可以显得十分简洁明了。并且当这种方式嵌入到Stream的处理流中,或者Lambda表达式中时,也是毫无违和感的。
这就是建造者模式在Java中的使用了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,612评论 18 399
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,647评论 18 139
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,645评论 0 11
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 7,094评论 0 62
  • 天气阴。黄沙漫天,空气质量严重污染。 事情杂乱,人不能乱。 今天算是满满当当的一天,然而这只是一个开始…学校的课程...
    W的两个世界阅读 205评论 0 0