美文网首页
建造者(Builder)模式

建造者(Builder)模式

作者: C调路过 | 来源:发表于2017-07-05 11:38 被阅读0次

    前言

    建造者模式即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

    相关文章

      网友评论

          本文标题:建造者(Builder)模式

          本文链接:https://www.haomeiwen.com/subject/xiofhxtx.html