设计模式-生成器(Builder)
一、概念
将一个复杂对像的构建与它的表示分离,使得同样的构建过程创建不同的表示,又叫建造模式。
生成器模式的重心在于分离构建算法和具体的构造实现,从而使得构建算法可以重用。采用不同的构建实现,产生不同的产品。所以生成器模式都会存在以下两个部分:
a.整体构建算法
b.部件的构造和产品的装配
二、模式动机
生成器模式主要的功能就是构建复杂的产品,且是细化的、分步骤的构建产品,生成器模式重在一步一步解决构造复杂对像的问题。
三、模式的结构

示意代码:
/**
*
* @ClassName: Product
* @Description: TODO(被构建的产品对像接品)
* @author beteman6988
* @date 2017年10月1日 上午11:26:33
*
*/
public interface Product { }
/**
* 成生器接口,定义构建一个产品对像所需要的各个部件的操作
* @ClassName: Builder
* @author beteman6988
* @date 2017年10月1日 上午11:28:12
*
*/
public interface Builder { /**
* 构建某个部件
* @Title: buildPart
* @param
* @return void
* @throws
*/
public void buildPart(); /**
* 获取最终生成的产品对像
* @Title: getResult
* @param @return
* @return Product
* @throws
*/
public Product getResult();
}
public class ConcreteBuilder implements Builder {
//最终构建的产品
private Product resultProduct;
/**
* 获取最终生成的产品
* @Title: getResult
* @param @return
* @return Product
* @throws
*/
@Override
public Product getResult() {
return this.resultProduct;
}
@Override
public void buildPart() {
// TODO Auto-generated method stub
}
}
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
/**
* 指导生成器构建最终的产品对像
* @Title: construct
* @param
* @return void
* @throws
*/
public void construct() {
builder.buildPart();
builder.getResult();
}
}
a.Builder:生成器接口,定义创建一个Product对像所需要的各个部件的操作。
b.ConcreteBuilder:具体生成器的实现,实现各个部件的创建,并负责组装Product对像的各个部件,同时还提供一个让用户获取组装完毕后的产品对像的方法。
c.Director:指导者,抽像出来的整体构建算法,主要用来使用Builder,以一个统一的过程来构建所需要的Product对像。
d.Product:产品,表示被生成器构建的复杂对像,包含多个部件。
四、模式样例
以一次台式机组装经历为例,当我们去电脑城组装电脑时,首先导购小妹妹会拿出一张打印好的空白配置报价单,我们在导购小妹的引导下,填写(当然小导购小妹填写)完了报价单后,然后组装工程师小哥就会跟据这个报价单,去仓库领取所有配件,然后就会将所有的配件组装在一起,一个完整的computer就组装好了,最后我们交钱拿电脑走人。
运用生成器模式对上述过程进行分析:
a.Product:导购小妹给我们的那个报价单可以说是一台最终computer product的一个抽像,当我们填写完一个一个完整的报价单后,可以说一个具体的compueter已经有了,
不过目前还是一堆零部件,要想得到一台完整的computer,还需要一个组装的过程。
b.Builder:我们的组装工程师小哥,跟据不同的具体报价单,都要去仓库忙一翻,要找到所有的部件,可以说只要有报价单,小哥都要将具体产口的每个部件都要找出来,少一个可以说都不行,这个可以说是一个完整电脑每个部件的抽像的建造(只是去仓库的相关位置拿到相关部件)。
c.ConcreteBuilder:组装工程师小哥跟据具体的报价单,去仓库找到相应的配件,并对每个部件进行处理,该拆封的拆封,该插线的插线,然后依据一定的步骤组装将所有配件组装起来,组装成一台完整的电脑。
d.Director:电脑的组装可以说有固定的套路,可以说这个套路适应于所有的电脑组装,比如必须先有机箱,然后将主板装到机箱上,然后将cpu装到主板上,步骤不能乱。按这个套路,工程师小哥跟据不同的报价单组装出不同的computer.

代码如下:
public interface CBuilder {
/**
* 构建机箱
* @Title: buildBox
* @param
* @return void
* @throws
*/
public void buildBox();
/**
* 安装主板
* @Title: buildMBoard
* @param
* @return void
* @throws
*/
public void buildMBoard();
/**
* 安装CPU
* @Title: buildCpu
* @param
* @return void
* @throws
*/
public void buildCpu();
/**
* 安装内存
* @Title: buildMemory
* @param
* @return void
* @throws
*/
public void buildMemory();
/**
* 安装硬盘
* @Title: buildHDisk
* @param
* @return void
* @throws
*/
public void buildHDisk();
/**
* 返回安装完毕的计算机
* @Title: getComputer
* @param @return
* @return ComputerA
* @throws
*/
public ComputerA getComputer();
}
public class ComputerABuilder implements CBuilder {
private ComputerA aComputer=new ComputerA();
@Override
public void buildBox() {
this.aComputer.setBox("MAtx");
}
@Override
public void buildMBoard() {
this.aComputer.setmBoard("AsusMb");
}
@Override
public void buildCpu() {
this.aComputer.setCpu("Intel CoreI7");
}
@Override
public void buildMemory() {
this.aComputer.setMemory("King stone DDR4");
}
@Override
public void buildHDisk() {
this.aComputer.sethDisk("West Hard Disk 1T");
}
@Override
public ComputerA getComputer() {
// TODO Auto-generated method stub
System.out.println("Box:"+this.aComputer.getBox());
System.out.println("MBoard:"+this.aComputer.getmBoard());
System.out.println("Cpu:"+this.aComputer.getCpu());
System.out.println("Memory:"+this.aComputer.getMemory());
System.out.println("HDisk:"+this.aComputer.gethDisk());
return aComputer;
}
}
public class ComputerA {
private String box;
private String mBoard;
private String cpu;
private String memory;
private String hDisk;
public ComputerA() {
super();
}
public String getBox() {
return box;
}
public void setBox(String box) {
this.box = box;
}
public String getmBoard() {
return mBoard;
}
public void setmBoard(String mBoard) {
this.mBoard = mBoard;
}
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String gethDisk() {
return hDisk;
}
public void sethDisk(String hDisk) {
this.hDisk = hDisk;
}
}
public class CDirector {
private CBuilder theCBuilder;
/**
* @roseuid 59DB89BE02A1
*/
public CDirector(CBuilder builder)
{
this.theCBuilder=builder;
}
/**
* 独立出来的构建过程
*/
public void construct()
{
this.theCBuilder.buildBox();
this.theCBuilder.buildMBoard();
this.theCBuilder.buildCpu();
this.theCBuilder.buildMemory();
this.theCBuilder.buildHDisk();
this.theCBuilder.getComputer();
}
}
public class Client {
public static void main(String[] args) {
CBuilder builder=new ComputerABuilder();
CDirector director=new CDirector(builder);
director.construct();
}
}
运行结果如下:
Box:MAtx
MBoard:AsusMb
Cpu:Intel CoreI7
Memory:King stone DDR4
HDisk:West Hard Disk 1T
五、模式的约束
对于以下情况应当使用生成器模式:
1.需要生成的产品对像有复杂的内部结构。每个内部成分可以是一个对像,也可以是产品的一个组成部分。
2.需要生产的产品的各个部件之间相互依赖,也就是一个部件的建造必须依赖另一个部件建造完成才能建造,生成器模式可以强制实行一种分步骤的建造过程。
3.在对像的创建过程中会使用到系统中的其它一些对像,这些对像在产品对像的创建过程中不易得到。
六、模式的变体与扩展
1.省略抽像生成器Builder角色,如果系统确定只会有一个具体生成器角色,那么就可以省略掉抽像生成器角色,类图如下:

2.省略指导者角色Director :如果抽像生成器Builder角色被省略,如上面的“1.”的情况,那么Director存在的意义就不大了,该角色也可以进行省略,如下图:

七、与其它模式的关系
1.生成器模式与工厂方法模式,这两个模式可以组合使用。生成器模式的Builder实现中,通常需要选择具体的部件实现。一个可行的方案就是实现为工厂方法,通常工厂方法来获取具体的部件对像,然后再进行部件的装配。
如下图:

2.生成器模式与抽像工厂模式,这两个模式是可以组合使用的,在生成器模式的Builder实现中,需要创建各个部件对像,而这些部件对像是有关联的,通常是构成的是一个复杂对像的部件对像。也就是说,Builder实现中,需要获取构成一个复杂对像的产品族,那自然就可以使用抽像工厂模式来实现,这样一来抽像工厂负责了部件对像的创建,Builder实现里面则主要负责产品对像的整体构建了。
如下图:

其实创建模式和抽像工厂模式两者还是有区别的,抽像工厂模式的主要目的是创建产品族,这个产品族里面的单个产品就相当于是构成一个复杂对像的部件对像,抽像工厂对像创建完成后就立即返回整个产品族;而生成器的模式的主要目的是按照构造算法,一步一步来构建一个复杂的产品对像,通常要等到整个构建过程结速后,才会得到最终的产品对像。
八、模式优缺点
生成器模式可以用同一个构建算法构建出表现上完全不同的产品,实现产品的构建和产品的表现上的分离。生成器模式正是把产品的构建过程独立出来,使它和具体产品的表现松散耦合,从而使得构建算法可以重用,而具体产品表现可以扩展和切换,从产品表现维度很好的支持开闭原则。
设计模式-生成器(Builder)的更多相关文章
- Objective-C设计模式——生成器Builder(对象创建)
生成器 生成器,也成为建造者模式,同样是创建对象时的设计模式.该模式下有一个Director(指挥者),客户端知道该类引用用来创建产品.还有一个Builder(建造者),建造者知道具体创建对象的细节. ...
- iOS设计模式 - 生成器
iOS设计模式 - 生成器 原理图 说明 1. 将构建复杂对象的过程拆分成一个一个的模块,通过统一的指导者来指导对象的构建过程称之为生成器模式 2. 生成器模式适合用于构建组合的对象 源码 https ...
- 设计模式:Builder模式
设计模式:Builder模式 一.前言 今天我们讨论一下Builder建造者模式,这个Builder,其实和模板模式非常的像,但是也有区别,那就是在模板模式中父类对子类中的实现进行操作,在父类之 ...
- Java设计模式之builder模式
Java设计模式之builder模式 今天学mybatis的时候,知道了SQLSessionFactory使用的是builder模式来生成的.再次整理一下什么是builder模式以及应用场景. 1. ...
- 设计模式之生成器(Builder)模式
意图 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以表示不同的表示. 适用性 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时. 当构造过程必须允许被构造的对象有不同的表 ...
- 2.5 《硬啃设计模式》第7章 车手选车 - 生成器(Builder Pattern)
某赛车游戏,玩家可以选择不同的车,这些车其实是采用不同性能的配件组成的,如:车胎.发动机等. 玩家选择一部车,其实就是new了一部车. 你如何考虑“new car”的代码? 要new这个车,可能需要先 ...
- C#设计模式——生成器模式(Builder Pattern)
一.概述在软件系统中,有时候面临着复杂的对象创建,该对象由一定算法构成的子对象组成,由于需求变化,这些子对象会经常变换,但组合在一起的算法却是稳定的.生成器模式可以处理这类对象的构建,它提供了一种封装 ...
- javascript设计模式-生成器模式(Builder)
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [学习笔记]设计模式之Builder
写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 作为一个新入职的魔导士呢,哦不,是程序员,我以为并没有太多机会去设计项目的软件架构.但是,工作一段时间之后,自己渐渐意识到,哪怕是自己 ...
随机推荐
- 异常处理,约束,MD5加密日志处理
程序运行过程中产生的错误, 不正常 def chufa(a, b): try: # 尝试执行xxx代码 ret = a/b # 如果这里出现了错误. 异常. 系统内部会产生一个异常对象. 系统会把这个 ...
- FunDA(17)- 示范:异常处理与事后处理 - Exceptions handling and Finalizers
作为一个能安全运行的工具库,为了保证占用资源的安全性,对异常处理(exception handling)和事后处理(final clean-up)的支持是不可或缺的.FunDA的数据流FDAPipeL ...
- joi库 学习笔记
零.背景 node.js 应用中,req.query / req.body 传来的参数需要做 valication( 合法性验证 ) 一.安装 https://github.com/hapijs/jo ...
- [Leetcode]146.LRU缓存机制
Leetcode难题,题目为: 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key ...
- POJ 2501
#include<iostream> #include<iomanip> #include<stdio.h> #include<string> #inc ...
- Error: insufficient funds for gas * price + value
有位同学今天用 web3+infura 获取 Rinkeby测试网络 的账号信息,报错如下: (node:18356) UnhandledPromiseRejectionWarning: Error: ...
- C#:WebBrowser控件的使用教程及相关问题整理
推荐阅读: C#WebBrowser控件使用教程与技巧收集--苏飞收集 C# WebBrowser强制在本窗口打开,禁止在新窗口打开 C# WebBrowser禁止在新窗口打开,强制在本窗口打开(多种 ...
- CLR关于语言文化的类型一CultureInfo类和字符串与线程的关联
.Net Frameword使用System.Globalization.Culture类型表示一个"语言/国家"对(根据RFC 1766标准).例如,'en-US'代表美国英语, ...
- Shell的并发
#!/bin/bash ./step1.sh & >中文 i=$! ./step2.sh & >西王 j=$! wait #echo ${i} #echo ${j} ech ...
- Windows下的Jdk 1.8*安装并配置(图文详解)
不多说,直接上干货! 简单说下,jdk1.8*的下载,见http://www.cnblogs.com/zlslch/p/5658383.html 双击jdk-8u60-windows-x64.exe运 ...