设计模式之美: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 的示例实现. 意图 通过明确地附加角色对象到目标对象中,以使对象可以适配不同的客户需求.每个角色对象都代 ...
随机推荐
- objective c,copy, mutableCopy区别
copy总是返回不能被修改的对象,mutableCopy返回可以被修改的对象 例: NSArray *array = @[@"test", @"test2"]; ...
- docker进程管理
docker进程管理:http://www.open-open.com/lib/view/open1455412749917.html 写的太好!!!!示例很清楚,很全面!! 我做个summary吧. ...
- zk源码环境搭建
zk不是使用maven管理的. 将zk的src下的代码导入eclipse,lib下的jar包导入工程. QuorumPeerMain类的main方法是入口,启动了zk的server,参数是conf文件 ...
- ios底层网络请求错误码
kCFHostErrorHostNotFound = 1, kCFHostErrorUnknown = 2, // Query the kCFGetAddrInfoFailureKey to get ...
- mysqldump操作参考
http://zhaizhenxing.blog.51cto.com/643480/134558 http://www.cnblogs.com/zeroone/archive/2010/05/11/1 ...
- HDU 4578 Transformation (线段树区间多种更新)
http://acm.hdu.edu.cn/showproblem.php?pid=4578 题目大意:对于一个给定序列,序列内所有数的初始值为0,有4种操作.1:区间(x, y)内的所有数字全部加上 ...
- CSS3--选择器
子元素选择器: div>p{background:yellow:} 相邻的后兄弟选择器(必须相邻) h1+p{padding-top:20px:} 后兄弟选择器(同级的当前元素后面的元素) di ...
- sbt的assembly插件使用(打包所有依赖)
1.sbt是什么 对于sbt 我也是小白, 为了搞spark看了一下scala,学习scala时指定的构建工具就是sbt(因为sbt也是用scala开发的嘛),起初在我眼里就是一个maven(虽然ma ...
- easyui中tree使用simpleData的形式加载数据
了解了zTree的使用, 发现它的simpleData是非常好用的, 由后台返回一个扁平数据, 直接在前台解析成树形菜单, 网上查了一下, easyui也可以简单实现, 不过....没看懂, 先记录一 ...
- HashedWheelTimer 原理
HashedWheelTimer 是根据 Hashed and Hierarchical Timing Wheels: Data Structuresfor the Efficient Impleme ...