设计模式之生成器(Builder)模式
意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以表示不同的表示。
适用性
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
- 当构造过程必须允许被构造的对象有不同的表示时。
UML图
- Builder ——为创建一个Product对象的各个部件指定抽象接口。
- ConcreteBuilder ——实现Builder的接口以构造和装配该产品的各个部件。
——定义并明确它所创建的表示。
——提供一个检索产品的接口。
- Director ——构造一个使用Builder接口的对象。
- Product ——表示被构造的复杂对象。
- ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
——包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
代码示例
ConcreteBuilder中需要提供构建产品的的各个部件的函数,以及对外获取被创建产品的接口。还是以创建迷宫为例,迷宫产品组件包括迷宫自身、房间、门,这些组件创建函数(BuildPart)需定义为虚函数,以便子类继承实现。在产品各部分创建好了后,需要通过对外的接口GetResult来获取创建的产品,本例GetMaze返回创建的迷宫。
class MazeBuilder{
public:
virtual void BuildMaze(){}
virtual void BuildRoom(int Room){}
virtual void BuildDoor(int roomFrom, int RoomTo){} virtual Maze* GetMaze(){return 0;}
protected:
MazeBuilder();
};
因为builder中BuildPart和GetResult函数都是虚函数,所以Director并不关心继承Builder的子类实现,Director只需要按部就班的调用Builder的BuildPart函数来创建产品,如下例:
builder.BuildMaze();//创建迷宫
builder.BuildRoom(1);//创建1号房间
builder.BuildRoom(2);//创建2号房间
builder.BuildDoor(1,2);//创建1号房间和2号房间的门
在产品各个部件创建完成后,调用:
build.GetMaze();//获取已创建迷宫
Maze* MazeGame::CreateMaze(MazeBuilder& builder){
builder.BuildMaze(); builder.BuildRoom(1);
builder.BuildRoom(2);
builder.BuildDoor(1,2); return builder.GetMaze();
}
MazeBuilder基类提供实现产品的接口,具体实现还需要子类来实现。这里StandardMazeBuilder继承MazeBuilder并实现了基本功能。
StandardMazeBuilder类声明:
class StandardMazeBuilder:public MazeBuilder{
public:
StandardMazeBuilder(); virtual void BuildMaze();
virtual void BuildRoom(int);
virtual void BuildDoor(int,int); virtual Maze* GetMaze();
private:
Direction CommonWall(Room *, Room *);
Maze * _currentMaze;
}
StandardMazeBuilder类实现:
#include "Builder.h" StandardMazeBuilder::StandardMazeBuilder(){
_currentMaze = 0;
} void StandardMazeBuilder::BuildMaze(){
_currentMaze = new Maze;
} Maze* StandardMazeBuilder::GetMaze(){
return _currentMaze;
} void StandardMazeBuilder::BuildRoom(int n){
if(!_currentMaze->RoomNo(n)){
Room* room = new Room(n);
_currentMaze->AddRoom(room); room->SetSide(North, new Wall);
room->SetSide(South, new Wall);
room->SetSide(East, new Wall);
room->SetSide(West, new Wall);
}
} void StandardMazeBuilder::BuildDoor(int n1, int n2){
Room *r1 = _currentMaze->RoomNo(n1);
Room *r2 = _currentMaze->RoomNo(n2);
Door *d = new Door(r1,r2); r1->SetSide(CommonWall(r1,r2),d);
r2->SetSide(CommonWall(r2,r1),d);
}
在实现了Director和Builder后,Client无需关心具体产品的具体实现,只需要新建该Builder类,传递给Director,就能创建出不同的产品了。
#include "Direcotr.h"
#include "StandardMazeBuilder.h" int Main(){ Maze *maze;
MazeGame game;
StandardMazeBuilder builder; game.CreateMaze(builder);
maze = builder.GetMaze();
return 0;
}
优缺点
优点:
- 将一个复杂对象的创建过程封装起来。
- 允许对象通过多个步骤来创建,并且可以改变过程(这和只有一个步骤的工厂模式不同)。
- 向客户隐藏产品内部的实现。
- 产品的实现可以被替换,因为客户只看到一个抽象的接口。
缺点:
- 与工厂模式相比,采用生成器创建对象的模式,需要具备更多的领域知识。
参考文献:
GOF《设计模式》
《Head First设计模式》
设计模式之生成器(Builder)模式的更多相关文章
- 设计模式 笔记 生成器(建造者)模式 Builder
//---------------------------15/04/08---------------------------- //builder 生成器(建造者)模式---对象创建型模式 /* ...
- Builder模式在Java中的应用
在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...
- Builder模式(建造者模式)
在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...
- Builder模式在Java中的应用(转)
在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...
- 每天一个设计模式-7 生成器模式(Builder)
每天一个设计模式-7 生成器模式(Builder) 一.实际问题 在讨论工厂方法模式的时候,提到了一个导出数据的应用框架,但是并没有涉及到导出数据的具体实现,这次通过生成器模式来简单实现导出成文本,X ...
- 设计模式03: Builder 生成器模式(创建型模式)
Builder生成器模式(创建型模式) Builder模式缘起假设创建游戏中的一个房屋House设施,该房屋的构建由几个部分组成,且各个部分富于变化.如果使用最直观的设计方法,每个房屋部分的变化,都将 ...
- 设计模式十: 生成器模式(Builder Pattern)
简介 生成器模式属于创建型模式的一种, 又叫建造者模式. 生成器模式涉及4个关键角色:产品(Product),抽象生成器(builder),具体生成器(ConcreteBuilder),指挥者(Dir ...
- 面向对象设计模式纵横谈:Builder 生成器模式(笔记记录)
Builder模式的缘起 假设创建游戏中的一个房屋House设施,该房屋的构建由几个部分组成,且各个部分要富于变化. 如果使用最直观的设计方法,每一个房屋部分的变化,都将导致房屋构建的重新修正…… 动 ...
- 设计模式之构建者模式(Builder):初步理解
构建者(Builder)设计模式(又叫生成器设计模式): 当一个类的内部数据过于复杂的时候(通常是负责持有数据的类,比如Config.VO.PO.Entity...),要创建的话可能就需要了解这个类的 ...
随机推荐
- 为什么在Python里推荐使用多进程而不是多线程
转载 http://bbs.51cto.com/thread-1349105-1.html 最近在看Python的多线程,经常我们会听到老手说:"Python下多线程是鸡肋,推荐使用多进程 ...
- react-dom.js 源码
/** *以下这是 react-dom.js 的源代码 * ReactDOM v15.3.1 * * Copyright 2013-present, Facebook, Inc. * All righ ...
- 1.4 PCI总线的中断机制
PCI总线使用INTA#.INTB#.INTC#和INTD#信号向处理器发出中断请求.这些中断请求信号为低电平有效,并与处理器的中断控制器连接.在PCI体系结构中,这些中断信号属于边带信号(Sideb ...
- SAS学习︱逻辑库、数据集创建与查看、数据库链接(SAS与R的code对照)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 入门学习一周,开始写学习笔记.用习惯R之后,发 ...
- VxWorks 符号表
符号表初始化 符号表用于建立符号名称.类型和值之间的关系.其中,名称为null结尾的任意字符串:类型为标识各种符号的整数:值为一个字符指针.符号表主要用来作为目标模块加载的基础,但 ...
- java.sql.SQLException:ORA-01861:文字和格式字符串不匹配
1.错误描述 java.sql.SQLException:ORA-01861:文字和格式字符串不匹配 2.错误原因 字段名为statis_date在数据库中存储的数据类型是Date,而在Java中拼接 ...
- python 实现多层目录文件查找
本文针对多层目录下文件的查找. 利用 os模块的基本操作,并利用递归的思想实现了目录多层查找. 代码如下: import os #dir_name: 处理文件的起始目录 def count_file( ...
- GridView中添加行单击事件.md
[toc] 1.使用说明 1.方法来源 该方法主要参考StackOverflow上面的答案和下面这篇文章 http://www.codeproject.com/Articles/15677/Click ...
- Python Web-第六周-JSON and the REST Architecture(Using Python to Access Web Data)
1.JavaScript Object Notation JSON 1.JSON 官方介绍 http://www.json.org/json-zh.html 2.json1.py import jso ...
- 第十篇:Map/Reduce 工作机制分析 - 数据的流向分析
前言 在MapReduce程序中,待处理的数据最开始是放在HDFS上的,这点无异议. 接下来,数据被会被送往一个个Map节点中去,这也无异议. 下面问题来了:数据在被Map节点处理完后,再何去何从呢? ...