java的builder模式详解:

  • 概念:
    建造者模式是较为复杂的创建型模式,它将客户端与多含多个组成部分(或部件)的复杂对象的创建过程分离。
  • 使用场景:
    当构造一个对象需要很多参数的时候,并且参数的个数或者类型不固定的时候。
  • UML结构图分析:

    下面具体介绍一下角色:
    Builder:它为创建一个产品Product对象的各个部件指定抽象接口。
    ConcreteBuilder:它实现了Builder接口,实现各个部件的具体构造和装配方法。
    Product:它是被构建的复杂对象,包含多个组成部件。
    Director:指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系。
  • 实际代码分析:
    先新建Product类:
    public class Product {
    /* 定义部件,部件可以是任意类型,包括值类型和引用类型 */
    private String partA;
    private String partB;
    private String partC; public String getPartA() {
    return partA;
    } public void setPartA(String partA) {
    this.partA = partA;
    } public String getPartB() {
    return partB;
    } public void setPartB(String partB) {
    this.partB = partB;
    } public String getPartC() {
    return partC;
    } public void setPartC(String partC) {
    this.partC = partC;
    } @Override
    public String toString() {
    return "Product{" +
    "partA='" + partA + '\'' +
    ", partB='" + partB + '\'' +
    ", partC='" + partC + '\'' +
    '}';
    }
    }

    然后再定义抽像的Builder类:

    abstract class Builder {
    //创建产品对象
    protected Product product = new Product(); public Product getResult() {
    return product;
    } protected abstract void buildPartA(); protected abstract void buildPartB(); protected abstract void buildPartC();
    }

    再定义具体的Builder类:

    /**
    * 具体构建者
    */
    public class ConcreteBuilder extends Builder {
    @Override
    protected void buildPartA() {
    product.setPartA("aaaa");
    } @Override
    protected void buildPartB() {
    product.setPartB("bbbb");
    } @Override
    protected void buildPartC() {
    product.setPartC("cccc");
    }
    }

    最后新建Director供客户端调用的指挥类:

    /**
    * 建造指挥者
    */
    public class Director { private Builder builder; public void setBuilder(Builder builder) {
    this.builder = builder;
    } public Director(Builder builder) {
    this.builder = builder;
    } //产品构建与组装方法
    public Product construct() {
    builder.buildPartA();
    builder.buildPartB();
    builder.buildPartC();
    return builder.getResult();
    }
    }

    然后客户端去使用一下:

    而如果修改构造细节:

    其结果也会变化:

    这里需要注意:在实际使用建造者模式时,可能只会用到ConcreteBuilder对像来构建,而不会完全按照UML类的结构来。

  • Builder模式优点:
    1、松散耦合:生成器模式可以用同一个构建算法构建出表现上完全不同的产品,实现产品构建与产品表现上的分离。
    2、可以很容易的改变产品的内部表示。
    3、更好的复用性:生成器模式很好的实现构建算法和具体产品实现的分离。
  • Builder模式缺点:
    会产生多余的Builder对象以及Director对象,消耗内存。

builder模式在android中的实际运用:

AlertDialog就是典型应用Builder模式的最好代表,下面来从代码角度来分析一下:

其中AlertController肯定是控制相关业务的,先来看一下它是在哪初始化的,很显然从构造方法中去找寻:

发现在是最后一个构造方法中去初始化的,具体如下:

接着来看一下AlertDialog.onCreate()方法:

此时看一下具体实现:

先不看具体细节,从这个调用层次来看真正实现业务逻辑的就是AlerController,接下来回到AlerDialog的Builder内部类:

然后在这个Builder类中有个onCreate()方法,如下:

接下来看一下这个apply的执行细节:

最后再来看一下AlertController.installContent()的细节:

调用的是父类的方法:

接着再来看一下这个方法:

设计模式相关面试问题-Builder基础详解与代码解读的更多相关文章

  1. 深入浅出DOM基础——《DOM探索之基础详解篇》学习笔记

    来源于:https://github.com/jawil/blog/issues/9 之前通过深入学习DOM的相关知识,看了慕课网DOM探索之基础详解篇这个视频(在最近看第三遍的时候,准备记录一点东西 ...

  2. Dom探索之基础详解

    认识DOM DOM级别 注::DOM 0级标准实际并不存在,只是历史坐标系的一个参照点而已,具体的说,它指IE4.0和Netscape Navigator4.0最初支持的DHTML. 节点类型 注:1 ...

  3. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  4. javaScript基础详解(1)

    javaScript基础详解 首先讲javaScript的摆放位置:<script> 与 </script> 可以放在head和body之间,也可以body中或者head中 J ...

  5. Python学习一:序列基础详解

    作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/7858473.html 邮箱:moyi@moyib ...

  6. Python学习二:词典基础详解

    作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/7862377.html 邮箱:moyi@moyib ...

  7. 三剑客基础详解(grep、sed、awk)

    目录 三剑客基础详解 三剑客之grep详解 1.通配符 2.基础正则 3.grep 讲解 4.拓展正则 5.POSIX字符类 三剑客之sed讲解 1.sed的执行流程 2.语法格式 三剑客之Awk 1 ...

  8. java继承基础详解

    java继承基础详解 继承是一种由已存在的类型创建一个或多个子类的机制,即在现有类的基础上构建子类. 在java中使用关键字extends表示继承关系. 基本语法结构: 访问控制符 class 子类名 ...

  9. java封装基础详解

    java封装基础详解 java的封装性即是信息隐藏,把对象的属性和行为结合成一个相同的独立单体,并尽可能地隐藏对象的内部细节. 封装的特性是对属性来讲的. 封装的目标就是要实现软件部件的"高 ...

随机推荐

  1. STS中MyBatis的基本实现

    本文采用的是<深浅spring boot 2.x>中第5章的例子,用一个接口实现对一个表项的读取. 数据库:mysql下建立user数据库,表名为t_usr 1. 数据源设置 在appli ...

  2. 字符串——kmp

    目录 一.前言 二.思路 三.代码 一.前言 kmp算法是用于从文本串text的字串中,寻找含有的模板串pattern的数量/位置的算法. 例如,在文本串abcabcccabc中,模板串abc的数量有 ...

  3. Windows10和Windows Server 2019支持OpenSSH

    从 Win10 1809 和 Windows Server 2019 开始 Windows 开始支持 OpenSSH Server.本文介绍一下其基本的概念和配置方法,本文演示用的环境为 Win10 ...

  4. Leetcode之动态规划(DP)专题-123. 买卖股票的最佳时机 III(Best Time to Buy and Sell Stock III)

    Leetcode之动态规划(DP)专题-123. 买卖股票的最佳时机 III(Best Time to Buy and Sell Stock III) 股票问题: 121. 买卖股票的最佳时机 122 ...

  5. PHP学习(4)——数组的使用

    1.数组的概念 数组就是一个用来存储一系列变量值的命名区域. 每个数组元素有一个相关的索引(也成为关键字),它可以用来访问元素. PHP允许间隔性地使用数字或字符串作为数组的索引. 2.数字索引数组 ...

  6. mac编译openJDK8

    买了<深入理解Java虚拟机> 周志明著这本书一直没有看,我们的程序都用JVM在跑,所以学习java必须掌握JVM,才能理解我们对象到底干嘛了.   1.为什么要编译JDK 想要一探JDK ...

  7. 第12课.经典问题解析(const;指针和引用)

    问题1:const什么时候为只读变量?什么时候是常量? const常量的判别准则: a.只有用字面量初始化的const常量才会进入符号表(直接初始化过的const为常量) b.被使用其他变量初始化的c ...

  8. 基于Docker 搭建 Jenkins

    ⒈下载镜像 要使用最新的LTS: docker pull jenkins/jenkins:lts 要使用最新的每周 docker pull jenkins/jenkins ⒉运行 docker run ...

  9. vimdiff、rev命令

    一.vimdiff:可视化比较工具 语法:       vimdiff [选项] file1 file2 [file3 [file4]] gvimdiff 描述       Vimdiff在两个(或三 ...

  10. 手动导入jar到本地mvn仓库

    <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId ...