建造者模式
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
介绍
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着”一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;
由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。
如何解决:将变与不变分离开。
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
应用实例:
1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的”套餐”。
2、JAVA 中的 StringBuilder。
优点:
1、建造者独立,易扩展。
2、便于控制细节风险。
缺点:
1、产品必须有共同点,范围有限制。
2、如内部变化复杂,会有很多的建造类。
使用场景:
1、需要生成的对象具有复杂的内部结构。
2、需要生成的对象内部属性本身相互依赖。
注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
实例(1)
建造者模式,又称生成器模式:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
三个角色:建造者、具体的建造者、监工、使用者(严格来说不算)
- 建造者角色:定义生成实例所需要的所有方法;
- 具体的建造者角色:实现生成实例所需要的所有方法,并且定义获取最终生成实例的方法;
- 监工角色:定义使用建造者角色中的方法来生成实例的方法;
- 使用者:使用建造者模式。
注意:定义中“将一个复杂的构建过程与其表示相分离”,表示并不是由建造者负责一切,而是由监工负责控制(定义)一个复杂的构建过程,由各个不同的建造者分别负责实现构建过程中所用到的所有构建步骤。不然,就无法做到“使得同样的构建过程可以创建不同的表示”这一目标。
建造者角色:
public abstract class Builder {
public abstract void buildPart1();
public abstract void buildPart2();
public abstract void buildPart3();
}
监工角色:
public class Director
{
// 将一个复杂的构建过程与其表示相分离
private Builder builder;
// 针对接口编程,而不是针对实现编程
public Director(Builder builder)
{
this.builder = builder;
}
public void setBuilder(Builder builder)
{
this.builder = builder;
}
public void construct()
{
// 控制(定义)一个复杂的构建过程
builder.buildPart1();
for (int i = 0; i < 5; i++) // 提示:如果想在运行过程中替换构建算法,可以考虑结合策略模式。
{
builder.buildPart2();
}
builder.buildPart3();
}
}
具体的建造者角色:
/**
* 此处实现了建造纯文本文档的具体建造者。
* 可以考虑再实现一个建造HTML文档、XML文档,或者其它什么文档的具体建造者。
* 这样,就可以使得同样的构建过程可以创建不同的表示
*/
public class ConcreteBuilder1 extends Builder
{
private StringBuffer buffer = new StringBuffer();//假设 buffer.toString() 就是最终生成的产品
@Override
public void buildPart1()
{
buffer.append("Builder1 : Part1\n"); //实现构建最终实例需要的所有方法
}
@Override
public void buildPart2() {
buffer.append("Builder1 : Part2\n");
}
@Override
public void buildPart3() {
buffer.append("Builder1 : Part3\n");
}
public String getResult()
{
return buffer.toString(); //定义获取最终生成实例的方法
}
}
客户角色:
public class Client
{
public void testBuilderPattern()
{
ConcreteBuilder1 b1 = new ConcreteBuilder1();//建造者
Director director = new Director(b1);//监工
director.construct();//建造实例(监工负责监督,建造者实际建造)
String result = b1.getResult();//获取最终生成结果
System.out.printf("the result is :%n%s", result);
}
}
实例(2)
1、定义以及 UML 建模图
将一个复杂对象的构建与它的表示分离,是的同样的构建过程可以创建不同的表示。
2、使用场景:
多个部件或者零件,都可以装配到一个对象中,但是产生的运行结果又相同。
产品类非常复杂,或者产品类中调用顺序不同产生了不同的作用。
初始化一个对象特别复杂,如使用多个构造方法,或者说有很多参数,并且都有默认值时。
3、核心类
- (1) 抽象产品类 computer。
- (2) Builder 抽象 Builder,规范产品的组建,一般是由子类实现具体的组建过程。
- (3)MacbookBuilder 具体的Builder类,具体的创建对象的类。
- (4) Directror 统一组建过程。
以组装一台计算机为主,主要进行组装主机,设置操作系统,设置显示器。
4、具体使用
Computer.java
//创建抽象类computer
public abstract class Computer {
protected String mBoard; //主机
protected String mDisplay; //显示器
protected String mOs; //操作系统
protected Computer(){
}
public void setBoard(String board){
mBoard=board; //initialize
}
public void setDisplay(String display) {
this.mDisplay = display;
}
public abstract void setOs() ;
@Override
public String toString() {
return "Computer{" +
"mBoard='" + mBoard + '\'' +
", mDisplay='" + mDisplay + '\'' +
", mOs='" + mOs + '\'' +
'}';
}
}
MacBook.java
//具体的创建对象的类。
public class MacBook extends Computer{
protected MacBook() {
}
@Override
public void setOs() {
mOs="Mac OS X 12"; //创建具体的对象,且重写了setOS
}
}
Builder.java
//规范产品的组建,一般是由子类实现具体的组建过程。
public abstract class Builder {
abstract void buildBoard(String board);
abstract void buildDisplay(String display);
abstract void buildOs(); //原始的是setOS
abstract Computer build(); //创建builder
}
MacBookBuilder.java
public class MacBookBuilder extends Builder {
private Computer mComputer=new MacBook();
@Override
void buildBoard(String board) {
mComputer.setBoard(board);
}
@Override
void buildDisplay(String display) {
mComputer.setDisplay(display);
}
@Override
void buildOs() {
mComputer.setOs();
}
@Override
Computer build() {
return mComputer;
}
}
4.5 Director类,负责具体的构造 Computer
Director.java
public class Director {
Builder mBuilser=null;
public Director(Builder builer) {
this.mBuilser = builer;
}
public void construct(String board,String display){
mBuilser.buildDisplay(display);
mBuilser.buildBoard(board);
mBuilser.buildOs();
}
}
Test.java
public class Test {
public static void main(String[] args){
Builder builder=new MacBookBuilder();
Director pcDirector=new Director(builder);
pcDirector.construct("英特尔主板","Retina显示器");
Computer computer = builder.build();
System.out.println(computer.toString());
}
}
5.总结
为了灵活构造复杂对象,该对象会有多个成员变量,在外部调用的时候,不需要或者不方便一次性创建出所有的成员变量,在这种情况下,使用多个构造方法去构建对象,很难维护,这时候Builder设计模式解决这个问题,进行buid()方法中创建对象,并且将builder传入,该builder中,维护了传入对象的成员变量。