一、模式说明

  在现实世界中,当我们要构造一个大型工程时(建一个大楼),通常的做法是先建造工程的每个独立部分,然后再逐步构造完成(先打地基,再搭框架,最后逐层累造)。在程序设计领域,构造一个复杂的类时(或一些具有类似结构的复杂类时),也可以采用类似的思想:如果要创建一个用于构造文档的类(或者是word,或者是html),虽然具体的文档有不同的结构,但是构造这些对象有相同的套路:创建标题,创建内容,创建条目,结束文档。Builder建造者模式就是用来构造复杂的类的。

二、模式类图

三、模式时序图

四、模式中的角色

  • Builder建造者:负责定义用于生成实例的接口(API),准备了生成实例的方法。
  • ConcreteBuilder具体的建造者:负责实现Builder角色的接口类(API),这里定义了生成实例时调用的方法,并且定义了获取最终生成结果的方法。
  • Director监工角色:负责使用Builder角色的接口(API)来生成实例。它并不依赖于具体的ConcreteBuilder角色,为了确保无论ConcreteBuilder如何被定义,Director角色都能正常工作,它只调用在Builder角色中被定义的方法。
  • Client使用者角色:使用Builder模式(Main 方法类)

五、代码示例

1、Builder建造者类:

package com.designpattern.cn.builderpattern;

public abstract class Builder {
public abstract void makeTitle(String title);
public abstract void makeString(String string);
public abstract void makeItems(String[] items);
public abstract void close();
}

抽象类,它定义了生成实例的接口。

2、Director监工:

package com.designpattern.cn.builderpattern;

public class Director {
public Builder builder;
public Director(Builder builder){
this.builder = builder;
} public void construct(){
builder.makeTitle("Greeting");
builder.makeString("A.M. to P.M.");
builder.makeItems(new String[]{
"Good morning",
"Good afternoon"
});
builder.makeString("Night");
builder.makeItems(new String[]{
"Good night",
"Bye"
});
builder.close();
}
}

注意Director的构造函数,它有一个Builder类型参数,但实际上并不能直接传递Builder实例(Builder是抽象类,无法构造实例),而是传递一个Builder的子类(TextBuilder或者是HtmlBuilder)

3、接下来是Builder的两个子类,它是实例类,可以创建对象。

package com.designpattern.cn.builderpattern;

public class TextBuilder extends Builder {
private StringBuffer buffer = new StringBuffer();
public void makeTitle(String title){
buffer.append("==================");
buffer.append("[" + title +"]");
buffer.append("\n");
}
public void makeString(String str){
buffer.append("[" + str + "\n");
buffer.append("\n");
}
public void makeItems(String[] items){
for (String item: items
) {
buffer.append(" ." + item + "\n");
}
buffer.append("\n");
}
public void close(){
buffer.append("==================");
}
public String getResult(){
return buffer.toString();
}
}
package com.designpattern.cn.builderpattern;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter; public class HtmlBuilder extends Builder {
private String filename;
private PrintWriter writer;
public void makeTitle(String title){
filename = title+".html";
try {
writer = new PrintWriter(new FileWriter(filename));
}catch (IOException e){
e.printStackTrace();
}
writer.println("<html><head><title>"+title+"</title></head><body>");
writer.println("<h1>"+title+"</h1>");
}
public void makeString(String str){
writer.println("<p>" + str + "</p>");
}
public void makeItems(String[] items){
writer.println("<ul>");
for (String s : items
) {
writer.println("<li>" + s + "</li>");
}
writer.println("</ul>");
}
public void close(){
writer.println("</body></html>");
writer.close();
}
public String getResult(){
return filename;
}
}

4、运行结果:

给程序传递参数:

运行结果:

传递html时的运行结果:

html显示效果:

六、相关的设计模式

  • Template Method模板方法模式:这个比较明显了:在一个类中定义方法和方法调用顺序,子类则实现方法,都是父类控制子类。
  • Composite组合模式:有些时候,可以用Builder模式生成的实例用于构成Composite组合模式。
  • Abstract Factory抽象工厂模式:都用于生成复杂的实例。
  • Facade模式:外观模式:通过组合内部模块,向外部提供可以简单调用的API,隐藏子系统的复杂性。

七、拓展思路

  • 【谁知道什么】在编程中,谁知道什么很重要,上面的程序Main客户端类并不知道Builder类,它只调用了Director监工类的construct建造方法,Director类就可以开始工作并完成文档创建。另一方面,Director知道Builder,它调用Builder的方法来构造文档,但是Director并不知道具体的Builder是谁(是哪个子类,plainText还是html?),也是正因为Director类不知道Builder是谁,才使得Builder可以被替换成不同的Builder子类。正因为不知道才可以替换。
  • 【设计阶段能决定什么,不能决定什么】Builder类中需要声明生成文档需要实现的所有方法,Director类中使用的方法都是Builder提供的,因此Builder类中应当定义哪些方法,这个问题很重要,需要慎重设计以应对程序后期变化。

一天一个设计模式——Builder建造者模式的更多相关文章

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

    1.建造者模式是一步一步创建一个复杂对象的创建模式.该模式是为了将构建复杂对象的过程和他的部件解耦,使得构建过程和部件表示隔离开. 2.Bulider模式的定义是:将一个复杂对象的构建与它的表示分离, ...

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

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

  3. Java设计模式之建造者模式(Builder)

    前言: 最近一直在学习okHttp,也对其做了一些整理,okHttp和Retrofit结合大大加速我们的开发效率,源码里面采用了很多设计模式,今天我们来学习一下其中的设计模式之一建造者模式. 建造者模 ...

  4. C#设计模式(5)——建造者模式(Builder Pattern)

    一.引言 在软件系统中,有时需要创建一个复杂对象,并且这个复杂对象由其各部分子对象通过一定的步骤组合而成.例如一个采购系统中,如果需要采购员去采购一批电脑时,在这个实际需求中,电脑就是一个复杂的对象, ...

  5. 乐在其中设计模式(C#) - 建造者模式(Builder Pattern)

    原文:乐在其中设计模式(C#) - 建造者模式(Builder Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 建造者模式(Builder Pattern) 作者:webabc ...

  6. C#设计模式之四建造者模式(Builder Pattern)【创建型】

    一.引言 今天我们要讲讲Builder模式,也就是建造者模式,当然也有叫生成器模式的,英文名称是Builder Pattern.在现实生活中,我们经常会遇到一些构成比较复杂的物品,比如:电脑,它就是一 ...

  7. 【GOF23设计模式】建造者模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]建造者模式详解类图关系 建造飞船 package com.test.Builder; public class AirShi ...

  8. 折腾Java设计模式之建造者模式

    博文原址:折腾Java设计模式之建造者模式 建造者模式 Separate the construction of a complex object from its representation, a ...

  9. Java 设计模式之建造者模式(四)

    原文地址:Java 设计模式之建造者模式(四) 博客地址:http://www.extlight.com 一.前言 今天继续介绍 Java 设计模式中的创建型模式--建造者模式.上篇设计模式的主题为 ...

随机推荐

  1. 2-10 就业课(2.0)-oozie:7、job任务的串联

    4.4.oozie的任务串联 在实际工作当中,肯定会存在多个任务需要执行,并且存在上一个任务的输出结果作为下一个任务的输入数据这样的情况,所以我们需要在workflow.xml配置文件当中配置多个ac ...

  2. linux中df和du查看磁盘大小不一致解决方法

    挂了一块50G到/data目录下#  df -h Filesystem Size Used Avail Use% Mounted on /dev/xvdb1 50G 46G 1.2G 98% /dat ...

  3. mysql性能优化及 Comparison method violates its general contract

    项目上嵌套结果集查询,查询的列表再根据每个id进行查询计算,嵌套的sql如下: SELECT SUM(IFNULL(t.out_rate,0)) totalOutRate, SUM(IF(IFNULL ...

  4. db.mysql.主从同步实验

    实验环境:windows10(1607).mysql5.7.16  (for windows zip) 主库(端口3306)配置文件: [mysqld] #数据库根目录 basedir = D:\my ...

  5. JVM:Java 类的加载机制

    虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验,转换,解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是虚拟机的类加载机制. 类的生命周期 类从被加载到虚拟机内 ...

  6. 06.swoole学习笔记--异步tcp服务器

    <?php //创建tcp服务器 $host='0.0.0.0'; $port=; $serv=new swoole_server($host,$port); //设置异步进程工作数 $serv ...

  7. 面试-PA和XSYX面试小结

    XSYX 1.自我介绍 2. 最近一个项目的业务和技术栈 3. 分布式锁解决库存问题 4. spring的IOC和AOP讲解 5. 类加载器层级 6.线程池核心参数和问题 7. 期待的团队是怎样的? ...

  8. 利用jQuery实现PC端href生效,移动端href失效

    今天要写一个功能,记录一下吧.if(navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)){ $('.item-a').attr('href' ...

  9. Most simple basic of internet programming based on two different machines sharing the same local net

    This blog is just shown for the most simple basic of internet programming based on two different mac ...

  10. 2的n次幂

    位运算判断2的n次幂: 举个栗子,n = 8:则二进制表示就为1000,n-1则为 0111 取&刚好等于0 嘿嘿,巧妙吧. 再举个栗子,n = 7: 则二进制为 0111,n-1则为0110 ...