一、模式解析

  建造模式是将复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入建造者和建造工具,对于内部是如何建造成成品的,调用者无需关心。

  以上是对建造者模式的官方定义,简单说就是对于复杂对象的创建,由一个建造者封装了对象组件的生成,由专门的指挥者来负责指挥对象生产和组件装配,调用者仅需要通知指挥者建造者进行生产,即可从对象本身获取完整对象。

  要点为:

  1、 模式的主要参与者为:抽象建造者,具体建造者,指挥者。

  2、具体建造者负责具体实施生产

  3、指挥者仅负责提供解决方案和流程

  4、最终的产品创建细节和产品交付由具体建造者负责

二、模式代码

定义产品的模块组成

package build.patten;

/**
* 产品的组成部分
* @author zjl
* @time 2016-1-29
*
*/
public class Part {
public String name; public Part(String name) {
super();
this.name = name;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.name.toString();
}
}

2、定义产品,产品由三个部分组成,因此保存一个组成部分的列表

package build.patten;

import java.util.ArrayList;
import java.util.List; /**
* 产品,可以包含A,B,C三个部分
* @author zjl
* @time 2016-1-29
*
*/
public class Product {
List<Part> parts=new ArrayList<Part>();
@Override
public String toString() {
// TODO Auto-generated method stub
return parts.toString();
} }

3、抽象的建造者,规定了对产品各部分的建造接口

package build.patten;

public interface IBuild {
public void buildPartA();
public void buildPartB();
public void buildPartC();
public Product getResult();
}

4、具体建造者,实现抽象建造者的方法,可以有一个或多个

package build.patten;

public class ConcreteBuild implements IBuild {
Product product=new Product(); @Override
public void buildPartA() {
// TODO Auto-generated method stub
product.parts.add(new Part("partA"));
} @Override
public void buildPartB() {
// TODO Auto-generated method stub
product.parts.add(new Part("partB"));
} @Override
public void buildPartC() {
// TODO Auto-generated method stub
product.parts.add(new Part("partC"));
} @Override
public Product getResult() {
// TODO Auto-generated method stub
return product;
} }

4、指挥者类,负责告诉建造者,应该以什么样的逻辑完成产品的创建

package build.patten;

public class Director {
IBuild build;
public Director(IBuild build){
this.build=build;
} public void build(){
this.build.buildPartA();
this.build.buildPartB();
this.build.buildPartC();
}
}

5、客户端

package build.patten;

public class Client {
public static void main(String[] args) {
IBuild build=new ConcreteBuild();
Director director=new Director(build);
director.build();
Product product=build.getResult();
System.out.println(product);
} }

6、运行结果,也就是创建的产品

[partA, partB, partC]

三、应用场景

建造者模式由于需要中间的指挥者来完成对产品各部分的建设,其实在工作中用的还是比较少,不过最近正在装修,似乎可以找到类似的原型:

在装修的过程中,我们将房子交给装修公司后,由设计师和工人来共同完成对房子的装修,其中设计师负责进行设计,规定房子如何装;具体干活:比如泥工,木工,电工均由工人完成。

整个装修过程比较复杂,因此我们选取简单的一块,比如门的设计和安装来举例:我的房子是两室一厨一卫,所以共需要四个门,门的牌子和材质可以有不同的选择,设计师负责进行选择,工人仅需要安装即可。

四、场景代码

1、定义门,

package build.example;

public class Door {
//名称
public String name;
//材料
public String type;
//位置
public String pos;
public Door(String name,String pos){
this.name=name;
this.pos=pos;
} @Override
public String toString() {
// TODO Auto-generated method stub
return pos+"的位置安装厂家为"+name+"的"+type+"门";
} }

定义房子,也就是最终交付的成果

package build.example;

import java.util.ArrayList;
import java.util.List; /**
* 房子装修,可以请装修工人对房子进行装修
* 不同人的房子可能装法不同
* 假设装修两室一厅,共四个门,厨卫+两个卧室
* @author zjl
* @time 2016-1-29
*
*/
public class House {
List<Door> doors=new ArrayList<Door>();
@Override
public String toString() {
// TODO Auto-generated method stub
return doors.toString();
}
}

3、定义工人,工人会装木门,也会装合金门

package build.example;
/**
* 抽象的装修工人,定义了装修工人会的技能
* 此处仅以装门来考虑
* @author zjl
* @time 2016-1-29
*
*/
public abstract class AbstractWorker { public abstract void fixMumen(Door door);
public abstract void fixHejinmen(Door door);
public abstract House getHouse(); }

4、定义一个具体的工人,每个工人手艺不一样,所以可以选择的工人很多,但他们都必须会装门

package build.example;

public class ConcreteWorkerA extends AbstractWorker {
public House house=new House();
@Override
public House getHouse(){
return house;
}
@Override
public void fixMumen(Door door) {
door.type="木";
house.doors.add(door); } @Override
public void fixHejinmen(Door door) {
door.type="合金";
house.doors.add(door);
} }

5、设计师,负责设计门如何安装

package build.example;
/**
* 设计师,负责设计门的的种类和选材
* @author zjl
* @time 2016-1-29
*
*/
public class Designer {
AbstractWorker worker;
public Designer(AbstractWorker worker){
this.worker=worker;
}
public void bulid() {
worker.fixMumen(new Door("A厂家", "厨房"));
worker.fixMumen(new Door("A厂家", "厕所"));
worker.fixHejinmen(new Door("A厂家", "主卧"));
worker.fixHejinmen(new Door("A厂家", "次卧"));
} }

6、我自己,只负责催进度和要结果

package build.example;

public class Client {
public static void main(String[] args) {
AbstractWorker worker=new ConcreteWorkerA();
Designer designer=new Designer(worker);
designer.bulid();
House house=worker.getHouse();
System.out.println(house);
}
}

7、生产结果

[厨房的位置安装厂家为A厂家的木门, 
厕所的位置安装厂家为A厂家的木门,
主卧的位置安装厂家为A厂家的合金门,
次卧的位置安装厂家为A厂家的合金门]

五、模式疑问:

  1、产品的交付,在模式标准中有建造者进行完成,似乎感觉由指挥者直接完成整个产品的返回似乎也可以,具体区别以后补充

  2、指挥者的存在是建造者模式的关键,将顺序剥离了建造者,其实我们完全可以将建造顺序和过程封装到抽象建造者内,此时建造者模式就变成了模板模式。

  3、针对第二点,为什么有了原型模式后,还会有建造者模式,其实建造者模式可以有多个指挥者,不同的指挥者可以设计出不同的建造顺序和逻辑,从而产生出不同的产品,例如我们装修时,找不同的设计师,设计出不同的风格,那么用的材料和牌子也会不同,此时原型模式由于在父类中规定了建造流程,反而无法达到此效果。

[工作中的设计模式]建造者模式builder的更多相关文章

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

    title: 设计模式-建造者模式 建造者模式(Builder)是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节.建造者模式属于对 ...

  2. [Head First设计模式]山西面馆中的设计模式——建造者模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 引言 将学习融入生活中,是件很happy的事情,不会感 ...

  3. 23种设计模式--建造者模式-Builder Pattern

    一.建造模式的介绍       建造者模式就是将零件组装成一个整体,用官方一点的话来讲就是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.生活中比如说组装电脑,汽车等等这些都是建 ...

  4. 设计模式--建造者模式Builder(创建型)

    一.首先看建造者模式的UML图: 二.再来看一个建造者模式的例子 class Builder { public: virtual void BuildHead() {} virtual void Bu ...

  5. 说说设计模式~建造者模式(Builder)

    返回目录 建造者模式是我的"设计模式"里创建型模式里的最后一篇,这种模式在实现中,很多架构都用到了,如MVC,MVP,MVVM,它们都是有建造者模式的精髓的,即,创建与表现分享,我 ...

  6. [工作中的设计模式]原型模式prototype

    一.模式解析 提起prototype,最近看多了js相关的内容,第一印象首先是js的原型 var Person=function(name){ this.name=name; } Person.pro ...

  7. 设计模式:建造者模式(Builder)

    流水作业大家应该都清楚吧!在流水作业中,我们可以将一些复杂的东西给构建出来,例如汽车.我们都知道汽车内部构件比较复杂,由很多部件组成,例如车轮.车门.发动机.方向盘等等,对于我们用户来说我们并不需要知 ...

  8. 设计模式 - 建造者模式 Builder Pattern

    简介 场景 在创建复杂对象时,用户无须关心该对象所包含的属性以及它们的组装方式,只需要指定复杂对象的类型和内容就可以构建它们. 模式定义 建造者模式:将一个复杂对象的构建与表示分离,使得同样的构建过程 ...

  9. [工作中的设计模式]解释器模式模式Interpreter

    一.模式解析 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 以上是解释器模式的类图,事实上我 ...

随机推荐

  1. EF查询视图只得到一条记录

    1.出错结果:数据库表视图有多条数据,在使用EF框架进行查询时却只得到一条数据(注:拦截EF得到的sql语句在数据库进行查询并没有任务问题). 2.出错原因:该视图中没有ID或者主键,EF查询时进行反 ...

  2. Linux面试题汇总答案

    转自:小女生的Linux技术~~~Linux面试题汇总答案~~ 一.填空题:1. 在Linux系统中,以 文件 方式访问设备 .2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的 ...

  3. [javascript]获取系统时间函数

    var oDate=new Date(); //初始化系统时间函数 alert(oDate.getHours()); //获取时 alert(oDate.getMinutes()); //获取分 al ...

  4. rsync使用

    1)拷贝本地文件.当SRC和DES路径信息都不包含有单个冒号":"分隔符时就启动这种工作模式.     如:rsync -a  ./test.c  /backup 2)使用一个远程 ...

  5. .NET微信公众号开发-2.0创建自定义菜单

    一.前言 开发之前,我们需要阅读官方的接口说明文档,不得不吐槽一下,微信的这个官方文档真的很烂,但是,为了开发我们需要的功能,我们也不得不去看这些文档. 接口文档地址:http://mp.weixin ...

  6. HTML标记之a标签

    一.a标签的语法 <a href=”链接目标地址” title=”注释” target=”打开链接窗口的形式”>链接显示内容</a> target值: _blank在新窗口中打 ...

  7. [Android Pro] 网络流量安全测试工具Nogotofail

    reference to : http://www.freebuf.com/tools/50324.html 从严重的HeartBleed漏洞到苹果的gotofail 漏洞,再到最近的SSL v3 P ...

  8. sp_who使用

    [SQL Server]  sp_who, sp_who2和sp_who3 sp_who可以返回如下信息: (可选参数LoginName, 或active代表活动会话数)Spid         (系 ...

  9. Nginx反向代理设置 从80端口转向其他端口

    [root@localhost bin]# netstat -lnutp Active Internet connections (only servers) Proto Recv-Q Send-Q ...

  10. Redis笔记(七)Java实现Redis消息队列

    这里我使用Redis的发布.订阅功能实现简单的消息队列,基本的命令有publish.subscribe等. 在Jedis中,有对应的java方法,但是只能发布字符串消息.为了传输对象,需要将对象进行序 ...