Android常见设计模式十:Build模式

对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次。而在android开发中,必要的了解一些设计模式又是必须的,因为设计模式在Android源码中,可以说是无处不在。对于想系统的学习设计模式的同学,这里推荐一本书,《大话设计模式》。


Android常用设计模式系列:

面向对象的基础特征
面向对象的设计原则
单例模式
模板模式
适配器模式
工厂模式
代理模式
原型模式
策略模式
Build模式
观察者模式
装饰者模式
中介模式
门面模式


Build模式

Build模式是非常常见的设计模式之一,写个笔记,记录一下我的学习过程和心得。

首先了解一些Build模式的定义。

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

但是看完这个定义,并没有什么卵用,你依然不知道什么是Builder设计模式。在此个人的态度是学习设计模式这种东西,不要过度在意其定义,定义往往是比较抽象的,学习它最好的例子就是通过样例代码。

我们通过一个例子来引出Builder模式。假设有一个Car类,我们通过该Car类来构建一大批汽车,这个Car类里有很多属性,最常见的比如颜色,价格,品牌,排量等等,并且我们允许这些值不被设置,也就是允许为null,该类的定义如下。

public class Car  {
    Color color;
    double price;
    String brand;
    String displacement;

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getDisplacement() {
        return displacement;
    }

    public void setDisplacement(String displacement) {
        this.displacement = displacement;
    }
}

然后我们为了方便可能会定义一个构造方法。

public Car(Color color, double price, String brand, String displacement) {
 this.color = color;
 this.price = price;
 this.brand = brand;
 this. displacement = displacement;
}

有时候,只想传部分参数,你还会定义如下类似的构造方法。

public Car(Color color) {
 this.color = color;
}
 public Car(Color color, double price) {
 this.color = color;
 this.price = price;
}
 public Car(Color color, double price, String brand) {
this.color = color;
 this.price = price;
 this.brand = brand;
} 

于是你就可以这样创建各个需要的对象

Person p2=new Person(Color.read);
Person p3=new Person(Color.blue,180000);
Person p4=new Person(Color.green,21180, "小鹏");
Person p5=new Person(Color.white,17170,"法拉利","4.0L"); 

可以想象一下这样创建的坏处,如果四个参都是同一种数据类型,那各个参数到底是什么意思,那得考读性了,。还有一个问题就是当有很多参数时,编写这个构造数就会显得异常麻烦,这时候如果换一个角度,试试Builder模式,你会发现代码的可读性一下子就上去了。

我们给Car增加一个静态内部类Builder类,并修改Car类的构造函数,代码如下。

public class Car  {
    Color color;
    double price;
    String brand;
    String displacement;

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getDisplacement() {
        return displacement;
    }

    public void setDisplacement(String displacement) {
        this.displacement = displacement;
    }

    private Car(Builder builder) {
 this.color = builder.color;
 this.price = builder.price;
 this.brand = builder.brand;
 this. displacement = builder.displacement;
    }
    
    
    public static class Builder {

    Color color;
    double price;
    String brand;
    String displacement;
        
        public  Builder color(Color color){
            this.color=color;
            return  this;
        }
        public  Builder price(double price){
            this.price=price;
            return  this;
        }
        public  Builder brand(String brand){
            this.brand=brand;
            return  this;
        }
        public  Builder displacement(String displacement){
            this.displacement=displacement;
            return  this;
        }


        public Car build() {
            return new Car(this);
        }
    }
}

这样,我们就不会被Car类构造函数的各个入参搞得稀里糊涂了。
此外Builder类中的成员函数返回Builder对象自身,让它支持链式调用,使代码可读性大大增强。于是我们就可以这样创建Car类。

new Car.Builder().color(Color.BLUE)
                 .price(129800)
                 .pailiang("1.5T")
                 .brand("小鹏")
                 .build();

有没有觉得创建过程一下子就变得那么清晰了。对应的值是什么属性一目了然,可读性大大增强。

综上,我们总结一下build模式的要点:

1. 定义一个静态内部类Builder,内部的成员变量和外部类一样
2. Builder类通过一系列的方法用于成员变量的赋值,并返回当前对象本身(this)
3. Builder类提供一个外部类的创建方法(build、create……),该方法内部调用了外部类的一个私有构造函数,入参就是内部类Builder
4. 外部类提供一个私有构造函数供内部类调用,在该构造函数中完成成员变量的赋值,取值为Builder对象中对应的成变量的值

模式应用广泛

其实在Android中, Builder模式也是被大量的运用。比如常见的对话框的创建

AlertDialog.Builder builder=new AlertDialog.Builder(this);
AlertDialog dialog=builder.setTitle("标题")
 .setIcon(android.R.drawable.ic_dialog_alert)
 .setView(R.layout.myview)
 .setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
 }
 })
 .setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
 }
 })
 .create();
dialog.show(); 

而且,各个第三方框架也大量的运用了Builder模式
如Gson中的GsonBuilder,代码太长了,就不贴了,有兴趣自己去看源码,这里只贴出其Builder的使用方法。

GsonBuilder builder=new GsonBuilder();
Gson gson=builder.setPrettyPrinting()
 .disableHtmlEscaping()
 .generateNonExecutableJson()
 .serializeNulls()
 .create(); 

再看看著名的网络请求框架OkHttp

Request.
Builder builder=new Request.Builder();
Request request=builder.addHeader("","")
 .url("")
 .post(body)
 .build();

总结

优点

Builder模式通常作为配置类的构建器将配置的构建和表示分离开来,同时也是将配置从目标类中隔离出来,避免作为过多的setter方法,并且隐藏内部的细节。Builder模式比较常见的实现形式是通过链式调用,这样使得代码更加简洁、易懂。

缺点

内部类与外部类相互引用,可能会导致内存消耗比较大,不过鉴于现在的手机内存来讲,这点几乎影响不大。

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

推荐阅读更多精彩内容