设计模式之美:Builder(生成器)
索引
意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Separate the construction of a complex object from its representation so that the same construction process can create different representations.
结构

参与者
Builder
- 为创建一个 Product 对象的各个部件指定抽象接口。
ConcreteBuilder
- 实现 Builder 的接口以构造和装配该产品的各个部件。
- 定义并明确它所创建的表示。
- 提供一个检索产品的接口。
Director
- 构造一个使用 Builder 接口的对象。
Product
- 表示被构造的复杂对象。ConcreteBuilder 创建该产品的内部表示并定义它的装配过程。
- 包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
适用性
在以下情况下可以使用 Builder 模式:
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
- 当构造过程必须允许被构造的对象有不同的表示时。
效果
- 它使你可以改变一个产品的内部表示。在改变该产品的内部表示时所要做的只是定义一个新的 ConcreteBuilder。
- 它将构造代码和表示代码分开,提高了对象的模块性。客户不需要知道定义产品内部结构的类的所有信息。
- 它使你可以对构造过程进行更精细的控制。对象是在 Director 的控制下一步一步构造的,仅当产品构造完成时 Director 才从 Builder 中取回它。
相关模式
- Abstract Factory 和 Builder 相似,因为它也可以创建复杂对象。区别是 Builder 着重于一步步构造一个复杂对象。而 Abstract Factory 着重于多个系列的产品对象(或简单或复杂)。Builder 是在最后一步返回产品,Abstract Factory 是立即返回。
- Composite通常是用 Builder 生成的。
实现

实现方式(一):Builder 为每个构件定义一个操作。
通常有一个抽象的 Builder 类为 Director 可能要求创建的每一个 "构件" 定义一个操作。这些操作默认情况下什么都不做。一个 ConcreteBuilder 类对它感兴趣的 "构件" 对应的操作进行重定义。
namespace BuilderPattern.Implementation1
{
public class ComplexProduct
{
public string ValueDependOnWeather { get; set; }
public string ValueDependOnFortune { get; set; }
} public abstract class AbstractComplexProductBuilder
{
protected ComplexProduct _complexProduct; public void BeginBuild(ComplexProduct existingComplexProduct = null)
{
if (existingComplexProduct == null)
_complexProduct = new ComplexProduct();
else
_complexProduct = existingComplexProduct;
} public virtual void BuildValueDependOnWeatherPart(string weather)
{
// could do nothing by default
_complexProduct.ValueDependOnWeather = weather;
} public virtual void BuildValueDependOnFortunePart(string luck)
{
// could do nothing by default
_complexProduct.ValueDependOnFortune = luck;
} public ComplexProduct EndBuild()
{
return this._complexProduct;
}
} public class ConcreteProductBuilderA : AbstractComplexProductBuilder
{
private string _dayOfWeek;
private int _luckyNumber; public ConcreteProductBuilderA(string dayOfWeek, int luckyNumber)
{
_dayOfWeek = dayOfWeek;
_luckyNumber = luckyNumber;
} public override void BuildValueDependOnWeatherPart(string weather)
{
// something customized
_complexProduct.ValueDependOnWeather = _dayOfWeek + " is " + weather;
} public override void BuildValueDependOnFortunePart(string luck)
{
// something customized
if (_luckyNumber == )
_complexProduct.ValueDependOnFortune = "Supper" + luck;
else
_complexProduct.ValueDependOnFortune = "Just so so" + luck;
}
} public class GoodWeatherAndGoodLuckDirector
{
public void ConstructWithGoodWeatherAndGoodLuck(AbstractComplexProductBuilder builder)
{
builder.BuildValueDependOnWeatherPart(@"PM2.5 < 50");
builder.BuildValueDependOnFortunePart(@"Good Luck");
} public void ConstructWithBadWeatherAndBadLuck(AbstractComplexProductBuilder builder)
{
builder.BuildValueDependOnWeatherPart(@"PM2.5 > 500");
builder.BuildValueDependOnFortunePart(@"Bad Luck");
}
} public class Client
{
public void TestCase1()
{
AbstractComplexProductBuilder builder = new ConcreteProductBuilderA("Sunday", );
GoodWeatherAndGoodLuckDirector director = new GoodWeatherAndGoodLuckDirector(); builder.BeginBuild();
director.ConstructWithGoodWeatherAndGoodLuck(builder);
ComplexProduct productWithGoodLuck = builder.EndBuild(); builder.BeginBuild();
director.ConstructWithBadWeatherAndBadLuck(builder);
ComplexProduct productWithBadLuck = builder.EndBuild();
}
}
}
实现方式(二):Builder 将构件返回给 Director,Director 将构件传递给 Builder 中的下一个步骤。
Builder 逐步的构造产品,所以其接口必须足够的普遍。如果构造过程中需要访问前面已经构造了的产品构件,则 Builder 将构件返回给 Director,由 Director 将构件传递给 Builder 中的下一个步骤。
namespace BuilderPattern.Implementation2
{
public class ComplexProduct
{
public string ValueDependOnWeather { get; set; }
public string ValueDependOnFortune { get; set; }
} public abstract class AbstractComplexProductBuilder
{
protected ComplexProduct _complexProduct; public void BeginBuild(ComplexProduct existingComplexProduct = null)
{
if (existingComplexProduct == null)
_complexProduct = new ComplexProduct();
else
_complexProduct = existingComplexProduct;
} public virtual string BuildValueDependOnWeatherPart(string weather)
{
// could do nothing by default
_complexProduct.ValueDependOnWeather = weather;
return _complexProduct.ValueDependOnWeather;
} public virtual string BuildValueDependOnFortunePart(string luck, string combinedWithWeather)
{
// could do nothing by default
_complexProduct.ValueDependOnFortune = luck + combinedWithWeather;
return _complexProduct.ValueDependOnFortune;
} public ComplexProduct EndBuild()
{
return this._complexProduct;
}
} public class ConcreteProductBuilderA : AbstractComplexProductBuilder
{
private string _dayOfWeek;
private int _luckyNumber; public ConcreteProductBuilderA(string dayOfWeek, int luckyNumber)
{
_dayOfWeek = dayOfWeek;
_luckyNumber = luckyNumber;
} public override string BuildValueDependOnWeatherPart(string weather)
{
// something customized
_complexProduct.ValueDependOnWeather = _dayOfWeek + " is " + weather;
return _complexProduct.ValueDependOnWeather;
} public override string BuildValueDependOnFortunePart(string luck, string combinedWithWeather)
{
// something customized
if (_luckyNumber == )
_complexProduct.ValueDependOnFortune = "Supper" + luck + combinedWithWeather;
else
_complexProduct.ValueDependOnFortune = "Just so so" + luck + combinedWithWeather;
return _complexProduct.ValueDependOnFortune;
}
} public class GoodWeatherAndGoodLuckDirector
{
public void ConstructWithGoodWeatherAndGoodLuck(AbstractComplexProductBuilder builder)
{
string weather = builder.BuildValueDependOnWeatherPart(@"PM2.5 < 50");
builder.BuildValueDependOnFortunePart(@"Good Luck", weather);
} public void ConstructWithBadWeatherAndBadLuck(AbstractComplexProductBuilder builder)
{
string weather = builder.BuildValueDependOnWeatherPart(@"PM2.5 > 500");
builder.BuildValueDependOnFortunePart(@"Bad Luck", weather);
}
} public class Client
{
public void TestCase2()
{
AbstractComplexProductBuilder builder = new ConcreteProductBuilderA("Sunday", );
GoodWeatherAndGoodLuckDirector director = new GoodWeatherAndGoodLuckDirector(); builder.BeginBuild();
director.ConstructWithGoodWeatherAndGoodLuck(builder);
ComplexProduct productWithGoodLuck = builder.EndBuild(); builder.BeginBuild();
director.ConstructWithBadWeatherAndBadLuck(builder);
ComplexProduct productWithBadLuck = builder.EndBuild();
}
}
}
《设计模式之美》为 Dennis Gao 发布于博客园的系列文章,任何未经作者本人同意的人为或爬虫转载均为耍流氓。
设计模式之美:Builder(生成器)的更多相关文章
- 设计模式03: Builder 生成器模式(创建型模式)
Builder生成器模式(创建型模式) Builder模式缘起假设创建游戏中的一个房屋House设施,该房屋的构建由几个部分组成,且各个部分富于变化.如果使用最直观的设计方法,每个房屋部分的变化,都将 ...
- 面向对象设计模式纵横谈:Builder 生成器模式(笔记记录)
Builder模式的缘起 假设创建游戏中的一个房屋House设施,该房屋的构建由几个部分组成,且各个部分要富于变化. 如果使用最直观的设计方法,每一个房屋部分的变化,都将导致房屋构建的重新修正…… 动 ...
- C#面向对象设计模式纵横谈——4.Builder 生成器模式(创建型模式)
动机 (Motivation) 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成:由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是它们组合 ...
- 设计模式之美:Creational Patterns(创建型模式)
创建型模式(Creational Patterns)抽象了对象实例化过程. 它们帮助一个系统独立于如何创建.组合和表示它的那些对象. 一个类创建型模式使用继承改变被实例化的类. 一个对象创建型模式将实 ...
- Builder生成器(创建型模式)
一.使用场景: 1.假设要创建一个House设施,该设施的创建由若干个部分组成,而且这若干个部分经常变化. 如果用最直观的设计方式,每一个房屋部分的变化,都将导致整个房屋结构的重新修正,但是这种设计方 ...
- 设计模式之美:Product Trader(操盘手)
索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Product Trader 的示例实现. 意图 使客户程序可以通过命名抽象超类和给定规约来创建对象. Product Trad ...
- 设计模式之美:Null Object(空对象)
索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Null Object 的示例实现. 意图 通过对缺失对象的封装,以提供默认无任何行为的对象替代品. Encapsulate t ...
- 设计模式之美:Dynamic Property(动态属性)
索引 别名 意图 结构 参与者 适用性 效果 实现 实现方式(一):Dynamic Property 的示例实现. 别名 Property Properties Property List 意图 使对 ...
- 设计模式之美:Role Object(角色对象)
索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Role Object 的示例实现. 意图 通过明确地附加角色对象到目标对象中,以使对象可以适配不同的客户需求.每个角色对象都代 ...
随机推荐
- singleTask, singleInstance使用心得
1. singleTask, singleInstance 共同点: 1) 一旦入栈,都为于栈底. 2) 全栈有且只有一个activity实例对象. 2. singleTask, singleIns ...
- 创建maven项目时,提示 overlaps the workspace location
创建maven项目时提示: Invalid project description.OKF:\java\mywork overlaps the workspace location: F:\java\ ...
- debian 8 和centos 配置java 环境变量的正确姿态
export JAVA_HOME=/usr/java/jre1.8.0_111export JAVA_BIN=/usr/java/jre1.8.0_111/binexport PATH=$PATH:$ ...
- handler 异步执行(进度条加载到100)
生明一个handler 对象(可重写handlerMessage 方法) 声明一个Runnable 对象,需重写run方法 按钮事件:handler对象实例的post方法调用线程. 线程的run方法开 ...
- css样式表 格式与布局
1 样式表 内联样式表 内嵌样式表 外部样式表 2 选择器 标签选择器 <style type="text\css" class 选择器 以.开头 ID选择器 以#开 ...
- zookeeper client 常用操作
#获取权限(类似于登陆) addauth digest admin-user:admin-password #查看权限 getAcl /collections/meixin_product/state ...
- Selenium2+python自动化17-JS处理滚动条
前言 selenium并不是万能的,有时候页面上操作无法实现的,这时候就需要借助JS来完成了. 常见场景: 当页面上的元素超过一屏后,想操作屏幕下方的元素,是不能直接定位到,会报元素不可见的. 这时候 ...
- 集合框架之 List
集合框架就是Java中解决数组长度固定的问题,相当于动态数组,随时用,随时建立,内存释放 这个问题还不知道? 整个集合框架 概括为 List Set Map 这三个接口以及他们的实现类之间的应 ...
- 由struts错误使用引发的漏洞,使用参数作为返回的文件路径或文件名,作为返回result 值
该错误可以导致他人任意访问该路径下的任何文件. struts 文件 <?xml version="1.0" encoding="UTF-8" ?> ...
- 解Tom大叔出的Javascript题目
原文参考,http://www.cnblogs.com/TomXu/archive/2012/02/10/2342098.html Tom大叔的博客深入理解Javascript系列真是我们学习Java ...