设计模式之美: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 的示例实现. 意图 通过明确地附加角色对象到目标对象中,以使对象可以适配不同的客户需求.每个角色对象都代 ...
随机推荐
- React学习之一:React初探
一,React简介 React是由Facebook和Instagram开发的一套创建用户界面的JavaScript库.许多人认为React是MVC中的V. React创建的目的是为了:构建数据随时会改 ...
- MySQL 5.7 深度解析: 半同步复制技术
复制架构衍生史 在谈这个特性之前,我们先来看看MySQL的复制架构衍生史. MySQL的复制分为四种: 普通的replication,异步同步. 搭建简单,使用非常广泛,从mysql诞生之初,就产生了 ...
- Sql 查找整个数据库中的字符串
--存储过程 CREATE PROCEDURE [dbo].[SP_FindValueInDB] ( @value VARCHAR() ) AS BEGIN SET NOCOUNT ON; DECLA ...
- NXP开源自动驾驶计算平台Bluebox 打造现实无人汽车
知名半导体制造商恩智浦NXP已经准备好了自家的自动驾驶计算开源平台Bluebox,将为汽车制造商提供现成的一体化自动 驾驶计算解决方案.专为自动驾驶设备的BlueBox中央计算引擎.不仅能够为无人驾驶 ...
- Oracle 11g AWR和ADDM性能报告
一.自动工作负载库(Automatic Workload Repository,AWR) 自动工作负载库(Automatic Workload Repository,AWR)是在Oracle公司提供的 ...
- java.io.Serializable 序列化问题
java.io.Serializable 序列化问题 Person.java package a.b.c; public class Person implements java.io.Seriali ...
- WebView加载本地Html文件并实现点击效果
Webview是用来与前端交互的纽,可以加载本地Html文件,和网页并实现交互的功能. WebView通过WebSetting可以使用Android原生的JavascriptInterface来进行j ...
- 图解 & 深入浅出 JavaWeb:Servlet必会必知
从[JavaEE 要懂的小事] Http相关,一直想写点Web开发相关的.最近项目接口开发紧,还有准备新的九月份战斗.JDK IO源码就隔一段落,温故知新看看Servlet & JSP 相关. ...
- 修改navigationbar右侧按钮离屏幕边缘位置
先上代码 UIButton *settingBtn = [Utils creatCustomButtonWithFrame:CGRectMake(, , , ) btnTitle: titleColo ...
- C语言 1 << 0 是什么意思
1 << 0 是把1 按2进制 左移0位,结果还是 1 ,2进制 0000 00011 << 1, 是把1 按2进制 左移1位,结果是2,2进制 0000 0010