生成器模式(Builder)
时间:2022-04-26
本文章向大家介绍生成器模式(Builder),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
生成器模式(Builder)
生成器模式(Builder)
意图:将一个对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。
应用:编译器词法分析器指导生成抽象语法树、构造迷宫等。
模式结构:
心得:
和工厂模式不同的是,Builder模式需要详细的指导产品的生产。指导者(Director)使用Construct方法构造产品BuilderProduct,但是它不直接参与构造过程,而是把构造的任务交给生成器(Builder)。Builder提供了产品每一个部件构造的实现方法(可以是默认实现),但是如果要获得最终的产品,需要派生Builder的子类,添加getResult方法返回最终的产品对象。BuildPart方法正是被指导者调用指挥产品生产流程的接口。
举例:
编译器中词法分析器为语法分析器提供基本的词法记号,这时可以将词法分析器看作一个指导者(Director),语法分析是为了获得一个语法树。词法分析器每次识别出一个词法结构时都会通知语法分析器,要求它做相应的语法结构匹配,直至最后生成最终的抽象语法树。这里使用一个简单词法分析的例子来说明Builder模式的实现:
//生成器接口
class Builder
{
protected:
Builder(){}
public:
virtual void addIntToken(){}
virtual void addIdentToken(){}
virtual void addSemiconToken(){}
virtual ~Builder(){}
};
//抽象语法树
class Tree
{
public:
void addNode(char*p)
{
cout<<"添加了一个"<<p<<"节点"<<endl;
}
void display()
{
cout<<"一颗完整的语法树"<<endl;
}
};
//抽象语法树生成器
class SemanticTreeBuilder:public Builder
{
Tree tree;
public:
SemanticTreeBuilder(){}
virtual void addIntToken()
{
tree.addNode("<Int>");
}
virtual void addIdentToken()
{
tree.addNode("<标识符>");
}
virtual void addSemiconToken()
{
tree.addNode("<分号>");
}
Tree getTree()
{
return tree;
}
};
//标识符个数生成器
class IdentCountBuilder:public Builder
{
int num;
public:
IdentCountBuilder():num(0){}
virtual void addIdentToken()
{
num++;
}
int getIdCount()
{
return num;
}
};
//词法分析器
class Parser
{
public:
//使用生成器生成对象
void Conctruct(Builder*builder)
{
builder->addIntToken();
builder->addIdentToken();
builder->addSemiconToken();
}
};
这里构造了两个生成器,一个用来生成抽象语法树,一个用来统计标识符的个数【先不考虑实际意义】。它们重写了标准接口定义的函数,并提供了自身的实现。前者返回抽象语法树对象,后者返回标识符个数。用户使用代码形式具有一致性和简洁性:
Parser par;//词法分析器
SemanticTreeBuilder treeBuilder;//语法树生成器
par.Conctruct(&treeBuilder);//构造语法树
Tree tree=treeBuilder.getTree();//获取构造的语法树
tree.display();//显示语法树
IdentCountBuilder idBuilder;//标识符个数生成器
par.Conctruct(&idBuilder);//获取标识符个数
cout<<"标识符个数="<<idBuilder.getIdCount()<<endl;//输出个数
使用Builder模式,可以通过改变接口的调用创建同类不同的产品,也可以改变Builder子类创建完全不同类的产品,并且保证用户能控制产品生产的细节和流程。
参考文章:http://blog.csdn.net/ldblog/article/details/2845591
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- SAP Spartacus storefrontapp index.html的design time和runtime
- OS开发爱好者福利来了:树莓派上编译C语言,顺便掌握一波硬件知识
- 一个简单易用的图标字体库和CSS框架fontawesome
- OLAP 数据平台 Druid 第一步,编写 Spec 配置
- 搭建 Kubernetes 集群 Dashboard 2.0+ 可视化插件
- Kubernetes 集群基本概念
- 未能幸免!安全容器也存在逃逸风险
- vue中v-for图片src路径错误
- 读书笔记 dotnet 什么时候进行垃圾回收
- Windows系统下ROS1或ROS2获取RTSP视频等功能包
- 本地存储
- 移动端click 延时解决方案
- 移动端返回顶部
- 移动端轮播图
- 移动端触屏事件