设计模式之生成器模式(Builder Pattern)生成器模式的优缺点生成器模式的实际应用生成器模式与工厂模式的不同
生成器模式的核心是 ** 当构建生成一个对象的时候,需要包含多个步骤,虽然每个步骤具体的实现不同,但是都遵循一定的流程与规则 **
举个例子,我们如果构建生成一台电脑,那么我们可能需要这么几个步骤
- 需要一个主机
- 需要一个显示器
- 需要一个键盘
- 需要一个鼠标
- 需要音响等
虽然我们具体在构建一台主机的时候,每个对象的实际步骤是不一样的,比如,有的对象构建了i7cpu的主机,有的对象构建了i5cpu的主机,有的对象构建了普通键盘,有的对象构建了机械键盘等。 但不管怎样,你总是需要经过一个步骤就是构建一台主机,一台键盘。 对于这个例子,我们就可以使用生成器模式来生成一台电脑,他需要通过多个步骤来生成。
所以,我们可以将生成器模式理解为,假设我们有一个对象需要建立,这个对象是由多个组件(Component)组合而成,每个组件的建立都比较复杂,但运用组件来建立所需的对象非常简单,所以我们就可以将构建复杂组件的步骤与运用组件构建对象分离,使用builder模式可以建立。
生成器模式的类图如下:
Paste_Image.png
下面我们就根据这个例子来实现一个生成器模式,生成一台电脑
首先我们需要一个电脑类:
package Builder;
public class Computer {
public String master;
public String screen;
public String keyboard;
public String mouse;
public String audio;
public void setMaster(String master) {
this.master = master;
}
public void setScreen(String screen) {
this.screen = screen;
}
public void setKeyboard(String keyboard) {
this.keyboard = keyboard;
}
public void setMouse(String mouse) {
this.mouse = mouse;
}
public void setAudio(String audio) {
this.audio = audio;
}
}
然后我们建立一个抽象的builder类:
package Builder;
public abstract class ComputerBuilder {
protected Computer computer;
public Computer getComputer() {
return computer;
}
public void buildComputer() {
computer = new Computer();
System.out.println("生成了一台电脑!!!");
}
public abstract void buildMaster();
public abstract void buildScreen();
public abstract void buildKeyboard();
public abstract void buildMouse();
public abstract void buildAudio();
}
然后我们实现两个具体的builder类,分别是惠普电脑的builder和戴尔电脑的builder
package Builder;
public class HPComputerBuilder extends ComputerBuilder {
@Override
public void buildMaster() {
// TODO Auto-generated method stub
computer.setMaster("i7,16g,512SSD,1060");
System.out.println("(i7,16g,512SSD,1060)的惠普主机");
}
@Override
public void buildScreen() {
// TODO Auto-generated method stub
computer.setScreen("1080p");
System.out.println("(1080p)的惠普显示屏");
}
@Override
public void buildKeyboard() {
// TODO Auto-generated method stub
computer.setKeyboard("cherry 青轴机械键盘");
System.out.println("(cherry 青轴机械键盘)的键盘");
}
@Override
public void buildMouse() {
// TODO Auto-generated method stub
computer.setMouse("MI 鼠标");
System.out.println("(MI 鼠标)的鼠标");
}
@Override
public void buildAudio() {
// TODO Auto-generated method stub
computer.setAudio("飞利浦 音响");
System.out.println("(飞利浦 音响)的音响");
}
}
package Builder;
public class DELLComputerBuilder extends ComputerBuilder {
@Override
public void buildMaster() {
// TODO Auto-generated method stub
computer.setMaster("i7,32g,1TSSD,1060");
System.out.println("(i7,32g,1TSSD,1060)的戴尔主机");
}
@Override
public void buildScreen() {
// TODO Auto-generated method stub
computer.setScreen("4k");
System.out.println("(4k)的dell显示屏");
}
@Override
public void buildKeyboard() {
// TODO Auto-generated method stub
computer.setKeyboard("cherry 黑轴机械键盘");
System.out.println("(cherry 黑轴机械键盘)的键盘");
}
@Override
public void buildMouse() {
// TODO Auto-generated method stub
computer.setMouse("MI 鼠标");
System.out.println("(MI 鼠标)的鼠标");
}
@Override
public void buildAudio() {
// TODO Auto-generated method stub
computer.setAudio("飞利浦 音响");
System.out.println("(飞利浦 音响)的音响");
}
}
然后我们实现一个director类:
package Builder;
public class Director {
private ComputerBuilder computerBuilder;
public void setComputerBuilder(ComputerBuilder computerBuilder) {
this.computerBuilder = computerBuilder;
}
public Computer getComputer() {
return computerBuilder.getComputer();
}
public void constructComputer() {
computerBuilder.buildComputer();
computerBuilder.buildMaster();
computerBuilder.buildScreen();
computerBuilder.buildKeyboard();
computerBuilder.buildMouse();
computerBuilder.buildAudio();
}
}
最后我们测试一下代码:
package Builder;
public class ComputerCustomer {
public static void main(String[] args) {
// TODO Auto-generated method stub
Director director = new Director();
ComputerBuilder hp = new HPComputerBuilder();
director.setComputerBuilder(hp);
director.constructComputer();
//get the pc
Computer pc = director.getComputer();
}
}
Paste_Image.png
生成器模式的优缺点
优点
- 将一个对象分解为各个组件
- 将对象组件的构造封装起来
- 可以控制整个对象的生成过程
缺点
对不同类型的对象需要实现不同的具体构造器的类,这可能回答大大增加类的数量
生成器模式的实际应用
Builder pattern has been used in a lot of libraries. However, there is a common mistake here. Consider the following example of StringBuilder which is a class from Java standard library. Does it utilize the Builder pattern?
生成器模式在许多类库中都使用了。但是严格来说,却有些错误。 比如这个例子,我们考虑java标准库中的StringBuilder类,它使用了生成器模式么?
StringBuilder strBuilder= new StringBuilder();
strBuilder.append("one");
strBuilder.append("two");
strBuilder.append("three");
String str= strBuilder.toString();
在标准库中,StringBuilder继承自AbstractStringBuilder append方法是这个生成过程中的一步,就像我们构建电脑时,先构建主机这样的步骤一样。 toString方法也是生成过程中的一步,而且是构建过程中的最后一步。然而,这里的不同是没有director,所以严格来说这不是一个标准的生成器模式。我们程序的调用者好像就是director可以生成我们自己的String。
生成器模式与工厂模式的不同
生成器模式构建对象的时候,对象通常构建的过程中需要多个步骤,就像我们例子中的先有主机,再有显示屏,再有鼠标等等,生成器模式的作用就是将这些复杂的构建过程封装起来。 工厂模式构建对象的时候通常就只有一个步骤,调用一个工厂方法就可以生成一个对象。
- Struts2、Spring MVC4 框架下的ajax统一异常处理
- 前11月网游收入1341亿元同比增超两成 你贡献了多少?
- struts2: config-browser-plugin 与 convention-plugin 学习
- 千万级规模高性能、高并发的网络架构经验分享
- UE4新手之编程指南
- redis 学习笔记(5)-Spring与Jedis的集成
- Linq to SQL 查询Tips
- SQLite 预写式日志
- java调用.net asmx / wcf
- mybatis3.2.8 与 hibernate4.3.6 混用
- mybatis的物理分页:mybatis-paginator
- 使用 WMI 进行诊断WCF
- java:快速文件分割及合并
- 暴涨210倍的一个数字货币正悄无声息崛起
- 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 数组属性和方法
- 你不知道c语言写的程序要多块——以NGS fastq文件reads计数为例
- JVM系列之:从汇编角度分析Volatile
- JVM系列之:从汇编角度分析NullCheck
- 基于机器学习的文本分类!
- JVM系列之:再谈java中的safepoint
- 《图解算法》第2章 选择排序
- 《图解算法》第3章 递归
- 《图解算法》第4章 快速排序
- 基于H5的Speedtest网速测试工具搭建
- Phaser类在性能测试中应用
- Mockito框架Mock Void方法
- 未来的神器fiddler Everywhere
- Sentinel整合Apollo进行规则持久化
- DevTools(Chrome 85)的新功能
- 在Node.js中处理Zip文件