(Builder Pattern)使用多个简单的对象一步一步创建成一个复杂的对象,属于创建性模式
介绍
意图: 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示
主要解决:在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构 成,由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定
何时使用:一些基本不会变,而其组合经常变化的时候
如何解决:将变与不变分离开
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系
应用实例:去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"
优点:1. 建造者独立,易扩展 2.便于控制风险
缺点:1.产品必须有共同点,范围有限制 2.如内部变化复杂,会有很多的建造类
使用场景:1. 需要生成的对象具有复杂的内部结构 2.需要生成的对象内部属性本身相互依赖
注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
模式结构和说明
建造者(生成器)模式的结构如图所示:
Builder:生成器接口,定义创建一个Product对象所需的各个部件的操作。 ConcreteBuilder: 具体的生成器实现,实现各个部件的创建,并负责组装product对象的各个部件,同时还提供一个让用户获取组装完成后的产品对象的方法 Director:指导者,也被称为导向者,主要用来使用Builder接口,以一个统一的过程来构建锁需要的Product对象 Product:产品,表示被生成器构建的复杂对象,包含多个部件
场景
需求: 写一份资料,开头必须是标题,日期,中间部分文本,结尾写编辑者,联系方式等
这还不简单,一份word文档Ok,但客户看了发现不直观,没有一点格式性,何况看着也麻烦,你给我弄成个HTML文件吧,又整一份.如果这个客户是个程序员,我想来个macdown文件呢,烦躁,太麻烦了一个文件而已要那么多格式,老子不干了
从开发的角度来做这件事,就是需要导出一个文件,但文件的格式不定,这怎么弄呢?仔细分析上面的问题,导出的文件,不管是什么格式,都分成三个部分,头文件,文件体和文件尾
怎么实现上述功能呢?下面来撸代码
不用模式的解决方案
- 首先定义文件头,文件体和文件尾
HeaderModel: {
String title,
String date
}
BodyModel:{
string body
}
FooterModel:{
string author
string connact
}
- 编写word格式,HTMl格式
class ExtportTxt{
exportTxt(HeaderModel header, BodyModel body, FooterModel footer)
{
String *txt = String()
txt.append(header.title)
txt.append(body.body)
txt.append(footer.author)
}
}
class ExtportHtml{
exportHtml(HeaderModel header, BodyModel body, FooterModel footer)
{
String *txt = String()
txt.append('<header>' +header.title+ '</header>')
//下面的格式暂不写了
txt.append(body.body)
txt.append(footer.author)
}
}
完美实现,但你会发现不论是什么格式,在实现的时候步骤基本是一样的,分为三步:
- 拼接头文件
- 拼接文件提
- 拼接文件尾
也就是说对于不同的输出格式,处理的步骤是一样的,但是每步的具体实现是不一样的,那咱们能不能把处理的步骤和具体的实现分开呢,这样就能复用处理过程
建造者模式来解决
定义:将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建出不同的表现
分析上面例子的实现,构建每种格式的数据文件的处理过程,不就是构建过程吗?而每种格式具体的步骤实现,不就是相当于不同的表示吗?因为不同步骤的实现,决定了最终的表现不同
要实现同样的构建过程可以创建不同的表现,那就把构建过程独立出来,在建造者模式中称为指导者,由它来完成指导装配过程,但不负责具体的实现.具体的实现对象在建造者模式中称为生成器
用模式来重写示例
-
数据模型不变
-
定义builder父类
Class Builder {
buildHeader(HeaderModel header)
buildBody(BodyModel body)
buildFooter(FooterModel footer)
}
- 具体的生成器
Class TxtBuilder:Builder {
String result = String()
buildHeader(HeaderModel header) {
result.append(header.title)
result.append(header.date)
}
buildBody(BodyModel body){
result.appen(body.body)
}
buildFooter(FooterModel footer){
footer.append(footer.author)
}
}
Class HTMLBuilder:Builder {
String result = String()
buildHeader(HeaderModel header) {
result.append("<header>"+header.title+"</header>")
result.append(header.date)
}
buildBody(BodyModel body){
result.appen("<body>"+body.body+"</body>")
}
buildFooter(FooterModel footer){
footer.append(footer.author)
}
}
- 指导者
Class Director {
Builder builder
createProduct(HeaderModel header, BodyModel body, FooterModel footer){
builder.builderHeader(header)
builder. buildBody(header)
builder. buildFooter(header)
}
}
解释
指导者承担的是整体构建算法部分,是相对不变的部分,也就是说构建过程是不变的,变化的部分都放在了生成器中
本质
生成器模式的本质:分离整体构建算法和部件构造