建造者(Builder)模式

前言

建造者模式即BUilder模式,看名字就可知是一种创建型模式。主要是解决

  1. 构造方法中参数过多导致的可读性较差的问题;
  2. 在初始化时不必将所有参数进行设置的情况(通常有默认值)。
    文中会举例进行演示,通过例子能够有一个更清晰的认识。

场景描述

许多游戏在进入游戏时,第一步往往是让我们选择角色的外形,如眼睛颜色,眼睛大小,发型,头发颜色,脸型等等。假设现在要创建一个小明,大眼,绿色的瞳孔,中分头,红色头发,鞋拔子脸。当然还有必填的姓名。

首先,我们创建一个Person的类,并改写toString方法便于测试。

public class Person {
    private String name;//姓名必填
    private String eyeSize;//眼睛大小
    private String eyeColor;//眼睛颜色
    private String hairStyle;//发型
    private String hairColor;//头发颜色
    private String face;//脸型

    public Person(String name, String eyeSize, String eyeColor, String hairStyle, String hairColor, String face) {
        this.name = name;
        this.eyeSize = eyeSize;
        this.eyeColor = eyeColor;
        this.hairStyle = hairStyle;
        this.hairColor = hairColor;
        this.face = face;
    }

    @Override
    public String toString() {
        String s = "姓名:" + name + "\n"
                + "眼睛:" + eyeSize + "\n"
                + "眼睛颜色:" + eyeColor + "\n"
                + "发型:" + hairStyle + "\n"
                + "头发颜色:" + hairColor + "\n"
                + "脸型:" + face;
        return s;
    }
}

同时我们编写测试类,创建小明这个角色。在创建时我郁闷了,在通过构造方法对对象进行初始化时,我忘记了参数的顺序。虽然现在IDE都非常的智能,会对参数进行提示,但是还是影响了我的开发效率。

最后我们艰辛的创建完了这个简单的测试类

public static void main(String[] args) {

    Person xiaoming = new Person("小明","大", "绿色", "中分", "红色", "鞋拔子脸");

    System.out.println(xiaoming.toString());

}

输入结果如下:

姓名:小明
眼睛:大
眼睛颜色:绿色
发型:中分
头发颜色:红色
脸型:鞋拔子脸

老铁,没毛病。但是现在是只有6个参数的情况下,似乎还可以接受,但是如果再多几个,orz!!

使用Builder模式

首先来说说使用Builder模式有什么优点:

  1. 默认参数,无需对所有参数进行初始化;
  2. 将实现变成链式调用,增加了代码可读性。

现在不管角色的外形,我只想创建一个小明的对象,来看看Builder模式会怎么做:

public static void main(String[] args) {
    Person xiaoming = new Person.Builder("小明").create();

    System.out.println(xiaoming.toString());
}
图片.png

Are you kidding?就传了个必填项姓名就创建好了?仅用一行代码就创建好了这个对象。

在前言中讲到过一点,设置默认值。以上实现就是基于默认值的设置。

接下来就来到了紧张刺激的代码实现环节。Builder的实现

public class Person {
    private String name;//姓名必填
    //省略其他可选参数

    private Person(Builder builder) {  //1............
        initialize(builder);
    }

    private void initialize(final Builder builder) {
        name = builder.name;
        //省略
    }


    public static class Builder {
        //2..........
        private String name;//姓名必填
        private String eyeSize = "大";//眼睛大小
        //省略

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

        public Builder setEyeSize(String eyeSize) {
            this.eyeSize = eyeSize;
            //3..........
            return this;
        }

        //省略

        //4..........
        public Person create() {
            return new Person(this);
        }
    }

    @Override
    public String toString() {
        String s = "姓名:" + name + "\n"
                + "眼睛:" + eyeSize + "\n"
                + "眼睛颜色:" + eyeColor + "\n"
                + "发型:" + hairStyle + "\n"
                + "头发颜色:" + hairColor + "\n"
                + "脸型:" + face;
        return s;
    }
}

划一下重点:

  1. 因为我们要用过Builder来创建对象,所有需将Person类的构造方法私有化,且通过Builder来构建;
  2. 在Builder中初始化变量,对外部提供set方法;
  3. 实现链式的关键 return this;
  4. 设置完参数之后通过Person类的构造进行构建并返回实例对象。

继续创建一个好看点的小红:

    Person xiaohong = new Person.Builder("小红")
            .setEyeColor("蓝色")
            .setEyeSize("大")
            .setFace("鹅蛋脸")
            .setHairStyle("大波浪")
            .setHairColor("褐色")
            .create();

是不是格外的清晰。

总结

将代码写成链式是非常优美的事情,像在Android开发中,我们可以将TitleBar的设置写成链式,也可以将RecyclerView的初始化过程写成链式;
看过dagger2生成的代码就可以看出,文中builder模式是仿造它的实现,要是没看过现在也可以转去看,相信会轻松许多;
完整代码移步gayhub

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

推荐阅读更多精彩内容