设计模式:Builder

简介

建造者模式(Builder),将一个复杂对象的表示和它的构建分离,这样同样的构造过程可以创建出不同的对象状态。

类图

下面的Product是要创建的对象的目标类型,产品。

  • Builder 创建一个Product对象涉及的操作的抽象接口,定义了Product各个部分的创建方法。
  • Director 使用Builder来构建Product,控制构建过程。
  • ConcreteBuilder 一个具体的构建者。

样例代码

目标类型Robot

假设要构建一个机器人Robot类型的对象:

public class Robot {
    private String head;
    private String arm;
    private String leg;
    private String body;

    // getter & setter 省略

    public String getDescription() {
        return toString();
    }

    @Override
    public String toString() {
        return "Robot{" +
                "head='" + head + '\'' +
                ", arm='" + arm + '\'' +
                ", leg='" + leg + '\'' +
                ", body='" + body + '\'' +
                '}';
    }
}

RobotBuilder

使用RobotBuilder接口(也可以是抽象类)来定义Robot各个部分的设置。

public interface RobotBuilder {
   void setArm();
   void setLeg();
   void setBody();
   void setHead();
}

具体的RobotBuilder

可以定义不同RobotBuilder子类来实现不同的Robot的构建。

BigRobotBuilder

构建一个“Big Robot”的建造器如下:

public class BigRobotBuilder implements RobotBuilder {
    private Robot mRobot;

    public BigRobotBuilder(Robot robot) {
        mRobot = robot;
    }

    @Override
    public void setArm() {
        mRobot.setArm("Big arm");
    }

    @Override
    public void setLeg() {
        mRobot.setLeg("Big leg");
    }

    @Override
    public void setBody() {
        mRobot.setBody("Big body");
    }

    @Override
    public void setHead() {
        mRobot.setHead("Big head");
    }
}

MiniRobotBuilder

构建一个“Mini Robot”的建造器如下:

public class MiniRobotBuilder implements RobotBuilder {
    private Robot mRobot;

    public MiniRobotBuilder(Robot robot) {
        mRobot = robot;
    }

    @Override
    public void setArm() {
        mRobot.setArm("Mini arm");
    }

    @Override
    public void setLeg() {
        mRobot.setLeg("Mini leg");
    }

    @Override
    public void setBody() {
        mRobot.setBody("Mini body");
    }

    @Override
    public void setHead() {
        mRobot.setHead("Mini head");
    }
}

RobotBuildDirector

控制Robot构建过程的指挥者:

public class RobotBuildDirector {
    public void buildRobot(RobotBuilder builder) {
        builder.setBody();
        builder.setArm();
        builder.setHead();
        builder.setLeg();
    }
}

如果构建过程需要严格顺序的话,那么Director来封装具体构建过程是很重要的。

调用代码

创建一个具体的builder,然后执行Director.buildRobot()来完成构建:

void main() {
    Robot robot = new Robot();
    RobotBuildDirector director = new RobotBuildDirector();
    RobotBuilder builder = new BigRobotBuilder(robot);
    director.buildRobot(builder);

    // 显示已构建的robot的详细信息
    Log.println(robot.getDescription());
}

小结

以上的Robot案例展示了builder模式的标准形式。 实际使用中,可能没有抽象Builder和Director控制过程这样的需要。 而是,仅仅希望将包含很多可设置的属性的类型的构建相关的代码与类型本身分开。 而且,设置属性的类往往就作为要配置的类的子类。

下面的实际案例中会说明这点。

实际案例

Diaglog

在Android开发中,AlertDialog类型的构建就使用到了Builder模式,而且是简化了的。

AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
AlertDialog dialog = dialogBuilder.setIcon(R.drawable.ic_launcher)
        .setMessage("message")
        .setTitle("Title")
        .setNegativeButton("Cancel", null)
        .create();

内部类AlertDialog.Builder用来对AlertDialog的不同的属性进行设置。 注意到setMessage()、setTitle()等方法都返回AlertDialog.Builder对象本身, 这样就可以以“链式代码”的形式对多个属性进行设置。这样的api很常见,如:

StringBuilder sb = new StringBuilder();
sb.append(1).append(2).append(2);

再如:

SharedPreferences sp = getSharedPreferences("1", MODE_PRIVATE);
sp.edit().putBoolean("1", false)
        .putInt("2", 2)
        .putLong("3", 3L)
        .remove("2")
        .apply();

可以看到,Builder对外暴露实际要使用的AlertDialog的各种属性的设置,而且它可以提供一些默认配置。这样使用者就无需每个属性都去指定。 当调用者完成对AlertDialog的一些方面的定制后,执行create()返回最终的dialog对象。

其它例子

Notification也是:

Notification.Builder builder = new Notification.Builder(this);
        Notification.Action action = null;
        String category = "";
        builder.addAction(action)
                .setCategory(category)
                .setColor(0xff00ff00)
                .setNumber(10086)
                .setGroup("groupKey")
                .build();

其它一些第三方库,或者非Android框架中也有类似Builder模式的大量运用,贵在积累和学习。

总结

可以看到,实际使用中的builder模式和标准的模式组成稍微不同。 很多已知的API中,对构建着模式的使用就是: 将一个包含很多不同属性的对象的设置相关逻辑封装为一个静态内部类去完成。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏向治洪

android自定义属性

1、引言 对于自定义属性,大家肯定都不陌生,遵循以下几步,就可以实现: 自定义一个CustomView(extends View )类 编写values/a...

214100
来自专栏非著名程序员

Retrofit OKHttp 教你怎么持久化管理Cookie

? 投稿作者:黄海杰 原文链接: http://blog.csdn.net/lyhhj/article/details/51345386 绪论 最近小编有点...

555100
来自专栏Java与Android技术栈

基于Kotlin的委托机制实现一个对Extra、SharedPreferences操作的库

本文介绍的库,github地址:https://github.com/fengzhizi715/SAF-Object-Delegate

16530
来自专栏影子

关于SpringMVC中如何把查询数据全转成String类型

36590
来自专栏Android开发指南

6.后台任务封装

29470
来自专栏Android知识点总结

1-SII--SharedPreferences完美封装

14240
来自专栏流媒体

MediaCodec进行AAC编解码(文件格式转换)

AAC,全称Advanced Audio Coding,是一种专为声音数据设计的文件压缩格式。与MP3不同,它采用了全新的算法进行编码,更加高效,具有更高的“性...

28150
来自专栏Android干货园

Retrofit+OKHttp 教你怎么持久化管理Cookie

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/51...

14630
来自专栏Android Note

RecyclerView 刷新闪烁

45870
来自专栏青青天空树

安卓OKhttp请求封装

  目前安卓开发中使用的网络工具为OKhttp,但是okhttp的使用还不是很方便,在okhttp的基础上再对请求进行封装会极大的方便网络调用。

25330

扫码关注云+社区

领取腾讯云代金券