Head First设计模式之生成器模式
一、定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。
二、结构
角色
- Builder(抽象建造者):它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两类方法,一类方法是buildPartX(),它们用于创建复杂对象的各个部件;另一类方法是getResult(),它们用于返回复杂对象。Builder既可以是抽象类,也可以是接口。
- ConcreteBuilder(具体建造者):它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象,也可以提供一个方法返回创建好的复杂产品对象。
- Product(产品角色):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。在本类图中,产品类是一个具体的类,而非抽象类。实际编程中,产品类可以是由一个抽象类与它的不同实现组成,也可以是由多个抽象类与他们的实现组成。
- Director(指挥者):指挥者又称为导演类,负责调用适当的建造者来组建产品,导演类一般不与产品类发生依赖关系,与导演类直接交互的是建造者类。一般来说,导演类被用来封装程序中易变的部分。
三、实现
背景:模拟生产各种笔(这里假设笔的零件生产是有顺序的:笔芯 -> 笔壳 -> 组装)
namespace DesignPatterns.Builder
{
class Program
{
static void Main(string[] args)
{
PenDirector director = new PenDirector();
Pen ballpointpen = director.ConstructPen(new BallpointPenBuilder());
Pen brushpen = director.ConstructPen(new BrushPenBuilder());
}
} /// <summary>
/// 创建抽象产品类 -- 笔
/// </summary>
public abstract class Pen
{
/**笔芯**/
private string _cartridge;
/**外壳**/
private string _shell; public string GetCartridge()
{
return _cartridge;
}
public void SetCartridge(string cartridge)
{
this._cartridge = cartridge;
}
public string GetShell()
{
return _shell;
}
public void SetShell(string shell)
{
this._shell = shell;
}
}
public interface IPenBuilder
{
/**
* 生产笔芯
*/
void BuildCartridge();
/**
* 生产外壳
*/
void BuildShell();
/**
* 组装笔
*/
Pen BuildPen();
} /// <summary>
/// 具体产品类 -- 圆珠笔
/// </summary>
public class BallpointPen : Pen
{ public BallpointPen()
{
Console.WriteLine("生产组装圆珠笔");
}
}
/// <summary>
/// 具体产品类 -- 画笔
/// </summary>
public class BrushPen : Pen
{ public BrushPen()
{
Console.WriteLine("生产组装画笔");
}
} /// <summary>
/// 建造者(具体) -- 圆珠笔builder
/// </summary>
public class BallpointPenBuilder : IPenBuilder
{ Pen _pen; public BallpointPenBuilder()
{
_pen = new BallpointPen();
} public void BuildCartridge()
{
_pen.SetCartridge("圆珠笔笔芯");
} public void BuildShell()
{
_pen.SetShell("圆珠笔外壳");
} public Pen BuildPen()
{
return _pen;
} } /// <summary>
/// 建造者(具体) -- 画笔builder
/// </summary>
public class BrushPenBuilder : IPenBuilder
{ Pen _pen; public BrushPenBuilder()
{
_pen = new BrushPen();
} public void BuildCartridge()
{
_pen.SetCartridge("画笔笔芯");
} public void BuildShell()
{
_pen.SetShell("画笔外壳");
} public Pen BuildPen()
{
return _pen;
} } /// <summary>
/// 导演类 Director
/// </summary>
public class PenDirector
{
public Pen ConstructPen(IPenBuilder penBuilder)
{
//生产笔芯
penBuilder.BuildCartridge();
//生产外壳
penBuilder.BuildShell();
//组装笔
return penBuilder.BuildPen();
}
}
}
四、适用场景
需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中。
隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
五、优缺点
优点:
封装性很好:使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。
扩展性很好:建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。
有效控制细节风险:由于具体的建造者是独立的,因此可以对建造者过程逐步细化,而不对其他的模块产生任何影响。
缺点:
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
欢迎阅读本系列文章:Head First设计模式之目录
Head First设计模式之生成器模式的更多相关文章
- 每天一个设计模式-7 生成器模式(Builder)
每天一个设计模式-7 生成器模式(Builder) 一.实际问题 在讨论工厂方法模式的时候,提到了一个导出数据的应用框架,但是并没有涉及到导出数据的具体实现,这次通过生成器模式来简单实现导出成文本,X ...
- Java设计模式:生成器模式
问题的提出: 有些类很容易创建对象,直接调用其构造方法,例如Student student = new Student("1001","zhang",21); ...
- 【设计模式】- 生成器模式(Builder)
生成器模式 建造者模式.Builder 生成器模式 也叫建造者模式,可以理解成可以分步骤创建一个复杂的对象.在该模式中允许你使用相同的创建代码生成不同类型和形式的对象. 生成器的结构模式 生成器(Bu ...
- Java设计模式-Builder生成器模式
概念: 生成器模式也称之为建造者模式.生成器模式的意图在于将一个复杂的构建与其表示相分离,构建与产品分离. UML: Ibuild接口清晰地反映了创建产品Product的流程. 生成器模式涉及4个关键 ...
- 面向对象设计模式_生成器模式详解(Builder Pattern)
首先提出一个很容易想到应用场景: 手机的生产过程:手机有非常多的子件(部件),成千上万,不同品牌的手机的生产过程都是复杂而有所区别的,相同品牌的手机在设计上也因客户需求多样化,大到型号,小到颜色,是否 ...
- 设计模式十: 生成器模式(Builder Pattern)
简介 生成器模式属于创建型模式的一种, 又叫建造者模式. 生成器模式涉及4个关键角色:产品(Product),抽象生成器(builder),具体生成器(ConcreteBuilder),指挥者(Dir ...
- 面向对象设计模式_生成器模式解读(Builder Pattern)
首先提出一个很容易想到应用场景: 手机的生产过程:手机有非常多的子件(部件),成千上万,不同品牌的手机的生产过程都是复杂而有所区别的,相同品牌的手机在设计上也因客户需求多样化,大到型号,小到颜色,是否 ...
- 设计模式--Builder生成器模式
如果文章中哪里有问题,希望各位大哥大姐指出,小弟十分感激. 正文 什么是生成器模式? 生成器模式就是把生产对象的过程进一步抽取.细化.独立.以往我们生产对象,可能就是在一个小作坊里面从头做到尾.现在用 ...
- go并发设计模式 --资源生成器模式
1.简单的生成器 package main import ( "fmt" "math/rand" ) func GenerateIntA()chan int { ...
随机推荐
- 匈牙利标记法定义ECMAScript变量前缀
匈牙利标记法定义ECMAScript变量前缀 类型 前缀 示例 数组 a aArray 布尔型 b bMale 浮点型(数字) f fTax 函数 fn fnSwap 整型(数字) i iAge ...
- 深入理解Mysql数据库主从延迟
1什么会增加主从延迟? 1 网络不好 2 从库硬件差 3 索引没做好,从库执行慢 4 从库锁等待,多见于myisam 5 主库写频繁,从库单线程执行慢 6 使用row复制,或mix使用行复制 2如何优 ...
- 在学java继承中
看到一片个人认为的好博客,http://www.cnblogs.com/dolphin0520/p/3803432.html ;这一节看的比较慢,加油,就是干: 分类不好意思分到Java中,嘿嘿还 ...
- 深入常用CSS声明(一) —— Background
一直对一些自己常用的css声明掌握得不是很全,只知道常用的一些属性和值,但是对于其他的用法确实一知半解,这篇文章旨在扫盲,先不说有多深的理解,至少做到能够看到这些声明的属性和值的时候做到不陌生. 这里 ...
- 大白话Vue源码系列(02):编译器初探
阅读目录 编译器代码藏在哪 Vue.prototype.$mount 构建 AST 的一般过程 Vue 构建的 AST 题接上文,上回书说到,Vue 的编译器模块相对独立且简单,那咱们就从这块入手,先 ...
- java学习笔记之集合家族1
集合 集合介绍: 由于数组中存放对象,对对象操作起来不方便.java中有一类容器,专门用来存储对象. 集合与数组的区别: 1.数组的长度固定的,而集合长度时可变的 2.数组只能储存同一类型的元素,而且 ...
- 移动 云MAS 发短信 .net HTTP 请求
本人开发移动云MAS .net Http 请求 代码如下 using Newtonsoft.Json.Linq; using System; using System.Collections.Gen ...
- webpack+babel+transform-runtime, IE下提示Promise未定义?
知识要求 babel的基础知识(推荐阮一峰的babel入门教程) 充分理解babel-plugin-transform-runtime与babel-runtime的作用(推荐github项目首页) w ...
- Elasticsearch布尔查询——bool
布尔查询允许我们利用布尔逻辑将较小的查询组合成较大的查询. 1.查询返回包含"mill"和"lane"的所有的账户 curl -XPOST 'localhost ...
- python 素因子分解
在使用python解决问题之前,我们先说一下,什么是素因子分解 所谓素因子分解就是,先找这个数的所有约数(约数即:a%b == 0,也就是a可以被b整除) 例如:20的约数集合为 [1, 2, 5, ...