简介

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

类图

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

  • Builder

    创建一个Product对象涉及的操作的抽象接口,定义了Product各个部分的创建方法。

  • Director

    使用Builder来构建Product,控制构建过程。

  • ConcreteBuilder

    一个具体的构建者。

样例代码

目标类型Robot

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

  1. public class Robot {
  2. private String head;
  3. private String arm;
  4. private String leg;
  5. private String body;
  6. // getter & setter 省略
  7. public String getDescription() {
  8. return toString();
  9. }
  10. @Override
  11. public String toString() {
  12. return "Robot{" +
  13. "head='" + head + '\'' +
  14. ", arm='" + arm + '\'' +
  15. ", leg='" + leg + '\'' +
  16. ", body='" + body + '\'' +
  17. '}';
  18. }
  19. }

RobotBuilder

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

  1. public interface RobotBuilder {
  2. void setArm();
  3. void setLeg();
  4. void setBody();
  5. void setHead();
  6. }

具体的RobotBuilder

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

BigRobotBuilder

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

  1. public class BigRobotBuilder implements RobotBuilder {
  2. private Robot mRobot;
  3. public BigRobotBuilder(Robot robot) {
  4. mRobot = robot;
  5. }
  6. @Override
  7. public void setArm() {
  8. mRobot.setArm("Big arm");
  9. }
  10. @Override
  11. public void setLeg() {
  12. mRobot.setLeg("Big leg");
  13. }
  14. @Override
  15. public void setBody() {
  16. mRobot.setBody("Big body");
  17. }
  18. @Override
  19. public void setHead() {
  20. mRobot.setHead("Big head");
  21. }
  22. }

MiniRobotBuilder

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

  1. public class MiniRobotBuilder implements RobotBuilder {
  2. private Robot mRobot;
  3. public MiniRobotBuilder(Robot robot) {
  4. mRobot = robot;
  5. }
  6. @Override
  7. public void setArm() {
  8. mRobot.setArm("Mini arm");
  9. }
  10. @Override
  11. public void setLeg() {
  12. mRobot.setLeg("Mini leg");
  13. }
  14. @Override
  15. public void setBody() {
  16. mRobot.setBody("Mini body");
  17. }
  18. @Override
  19. public void setHead() {
  20. mRobot.setHead("Mini head");
  21. }
  22. }

RobotBuildDirector

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

  1. public class RobotBuildDirector {
  2. public void buildRobot(RobotBuilder builder) {
  3. builder.setBody();
  4. builder.setArm();
  5. builder.setHead();
  6. builder.setLeg();
  7. }
  8. }

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

调用代码

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

  1. void main() {
  2. Robot robot = new Robot();
  3. RobotBuildDirector director = new RobotBuildDirector();
  4. RobotBuilder builder = new BigRobotBuilder(robot);
  5. director.buildRobot(builder);
  6. // 显示已构建的robot的详细信息
  7. Log.println(robot.getDescription());
  8. }

小结

以上的Robot案例展示了builder模式的标准形式。

实际使用中,可能没有抽象Builder和Director控制过程这样的需要。

而是,仅仅希望将包含很多可设置的属性的类型的构建相关的代码与类型本身分开。

而且,设置属性的类往往就作为要配置的类的子类。

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

实际案例

Diaglog

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

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

内部类AlertDialog.Builder用来对AlertDialog的不同的属性进行设置。

注意到setMessage()、setTitle()等方法都返回AlertDialog.Builder对象本身,

这样就可以以“链式代码”的形式对多个属性进行设置。这样的api很常见,如:

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

再如:

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

可以看到,Builder对外暴露实际要使用的AlertDialog的各种属性的设置,而且它可以提供一些默认配置。这样使用者就无需每个属性都去指定。

当调用者完成对AlertDialog的一些方面的定制后,执行create()返回最终的dialog对象。

其它例子

Notification也是:

  1. Notification.Builder builder = new Notification.Builder(this);
  2. Notification.Action action = null;
  3. String category = "";
  4. builder.addAction(action)
  5. .setCategory(category)
  6. .setColor(0xff00ff00)
  7. .setNumber(10086)
  8. .setGroup("groupKey")
  9. .build();

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

总结

可以看到,实际使用中的builder模式和标准的模式组成稍微不同。

很多已知的API中,对构建着模式的使用就是:

将一个包含很多不同属性的对象的设置相关逻辑封装为一个静态内部类去完成。

(本文使用Atom编写)

设计模式:Builder的更多相关文章

  1. 设计模式Builder(建造者)模式

    1.出现原因 在软件系统中,有时候会面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成:由于需求的变化,这个复杂的对象的各个部分可能面临着剧烈的变化,但是把他们组合在一起的算法 ...

  2. 设计模式-----Builder模式

    前言 近日,看到Myabtis中组件中SqlSessionFactory由SqlSessionFactoryBuilder().build()生成时,且采用Builder模式,遂记录学习之. SqlS ...

  3. java设计模式--Builder模式

    一.Builder模式 二.使用例子 三.Spring中的Builder模式 Builder模式,构建者.构造者模式,在<图解设计模式>中归为 生成实例 一栏,该模式用于组装具有复杂结构的 ...

  4. 设计模式-Builder和Factory模式区别

    Builder和Factory模式区别 Builder模式结构: Factory模式一进一出,Builder模式是分步流水线作业.当你需要做一系列有序的工作或者按照一定的逻辑来完成创建一个对象时 Bu ...

  5. 设计模式-Builder模式(创建型模式)

    //以下代码来源: 设计模式精解-GoF 23种设计模式解析附C++实现源码 //Product.h #pragma once class Product { public: Product(); ~ ...

  6. Java设计模式-Builder构造者模式

    介绍: 构造者模式,又称之为建造者模式,建造者模式,单例模式以及工厂模式都属于创建型模式1应用场景 今天学mybatis的时候,知道了SQLSessionFactory使用的是builder模式来生成 ...

  7. 一天一个设计模式——Builder建造者模式

    一.模式说明 在现实世界中,当我们要构造一个大型工程时(建一个大楼),通常的做法是先建造工程的每个独立部分,然后再逐步构造完成(先打地基,再搭框架,最后逐层累造).在程序设计领域,构造一个复杂的类时( ...

  8. C++设计模式-Builder建造者模式

    作用:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. Builder模式和AbstractFactory模式在功能上很相似,因为都是用来创建大的复杂的对象,它们的区别是:B ...

  9. Java设计模式-Builder生成器模式

    概念: 生成器模式也称之为建造者模式.生成器模式的意图在于将一个复杂的构建与其表示相分离,构建与产品分离. UML: Ibuild接口清晰地反映了创建产品Product的流程. 生成器模式涉及4个关键 ...

  10. java的设计模式 - Builder模式

    Builder 模式的目的? 构造对象的方式过于复杂,不如将之抽离出来.比如,构造器参数过多 这样说也有点抽象,举个例子吧. 举个例子 比如 非常热门的消息队列RabbitMQ 的 AMQP.Basi ...

随机推荐

  1. 跟我学Spring Boot(三)Spring Boot 的web开发

    1.Web开发中至关重要的一部分,Web开发的核心内容主要包括内嵌Servlet容器和SpringMVC spring boot  提供了spring-boot-starter-web 为web开发提 ...

  2. spring学习 十五 spring的自动注入

    一  :在 Spring 配置文件中对象名和 ref=”id” ,id 名相同使用自动注入,可以不配置<property/>,对应的注解@Autowired的作用 二: 两种配置办法 (1 ...

  3. navigator - 定时器 - event

    1. navigator userAgent: 包含浏览器名称,内核,版本号的字符串 鄙视: 如何判断浏览器名称和版本号 2. 定时器: 2种: 1. 周期性定时器: 什么是: 让程序每隔一段时间间隔 ...

  4. linux_开启mysql服务

    想要连接mysql的时候必须先开启mysql的服务 service mysqld start mysql -u root -p 输入密码

  5. 通俗理解 CPU && GPU

    CPU 力气大啥P事都能干,还要协调.GPU 上面那家伙的小弟,老大让他处理图形,这方面处理简单,但是量大,老大虽然能处理,可是老大只有那么几个兄弟,所以不如交给小弟处理了,小弟兄弟多,有数百至数千个 ...

  6. OpenCV(2):视频

    播放AVI视频 #include<iostream> #include<opencv2/core/core.hpp> #include<opencv2/highgui/h ...

  7. android studio友盟分享demo运行报错Gradle's dependency cache may be corrupt解决方法

    gradle-wrapper.properties里修改了gradle的版本,与之前没有报错的项目gradle版本一致.

  8. IntelliJ IDEA 2017版 spring-boot 2.0.3 邮件发送搭建,概念梳理 (二)

    第二部分 邮件发送历史   一.第一封邮件   1.1969年10月,世界上的第一封电子邮件    1969年10月世界上的第一封电子邮件是由计算机科学家Leonard K.教授发给他的同事的一条简短 ...

  9. R语言的文件写入

    R语言的文件写入 官方文档介绍如下: write.table(x, file = "", append = FALSE, quote = TRUE, sep = " &q ...

  10. Docker Compose部署lnmp

    参考:https://github.com/micooz/docker-lnmp 一.简介 使用Dcoekr镜像部署lnmp(Linux.Nginx.MySQL.PHP7). 1.1 结构 app └ ...