摘要:建造者模式是创建型模式大类中的一种,在面向对象的语言中无时无刻不在进行者对象的创建,下面来学习一下建造者模式来创建对象。
在这篇文章中我们来学习一下下面几个问题
1、什么是建造者模式
2、使用建造者模式创建产品
3、为何要用建造者模式,在怎样的场景下使用建造者模式
4、演变后的建造者模式
5、演变后的建造者模式相比构造函数和setter的优缺点
一、建造者模式
1、建造者模式定义
(1)、建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
(2)、建造模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们,用户不知道内部的具体构建细节,构建过程对用户是隐藏的。
建造者模式UML图:

2、建造者模式各个角色
(1)、Product: 要建造的产品
(2)、抽象的Builder: 建造过程具体建造步骤的抽象
(3)、ConcreteBuilder建造者实现抽象类Builder: 实现Builder 就具体建造抽象步骤
(4)、Director: 指导者,指导构建过程;实现用户和构建的分离。
二 、对象创建
我们这里使用建造者创建不同配置的手机如pro 、标配。
按照上面的UML图其中有四个角色,产品、抽象构建过程、具体构建过程、指导者show me code……
1、需要的产品定义、建造者创建产品
package com.sb.design;
/***
* product
*/
public class Phone {
/**
* 处理器
*/
private String cpu;
/**
* 内存
*/
private String ram;
/**
* 像素
*/
private Integer pixel;
/**
* 电池容量
*/
private Integer battery;
public void setCpu(String cpu) {
this.cpu = cpu;
}
public void setRam(String ram) {
this.ram = ram;
}
public void setPixel(Integer pixel) {
this.pixel = pixel;
}
public void setBattery(Integer battery) {
this.battery = battery;
}
public String getCpu() {
return cpu;
}
public String getRam() {
return ram;
}
public Integer getPixel() {
return pixel;
}
public Integer getBattery() {
return battery;
}
@Override
public String toString() {
return new StringBuffer().append("处理器:").append(cpu).append(" 内存:").append(ram).append(" 像素:").append
(pixel).append(" 电池容量:").append(battery).toString();
}
}
2、建造流程、步骤是固定的,所有建造者都是按照这个流程来建造具体产品,所以抽象这个创建流程。
package com.sb.design;
/***
* 建造过程抽象
*/
public interface PhoneBuilder {
/**
* 处理器
*/
void setCpu();
/**
* 内存
*/
void setRam();
/**
* 像素
*/
void setPixel();
/**
* 电池
*/
void setBattery();
/**
* 组装
*
* @return
*/
Phone build();
}
3、按照用户需求,实现不同创建者、但是产品创建的流程确定,所以实现创建流程接口;具体产品创建操作。
(1)、高配手机创建
package com.sb.design;
/***
* 高配手机建造者
*/
public class ProPhoneBuilder implements PhoneBuilder {
Phone phone;
{
phone = new Phone();
}
public ProPhoneBuilder() {
}
@Override
public void setCpu() {
phone.setCpu("加强版");
}
@Override
public void setRam() {
phone.setRam("256G");
}
@Override
public void setPixel() {
phone.setPixel(10000);
}
@Override
public void setBattery() {
phone.setBattery(20000);
}
@Override
public Phone build() {
return phone;
}
}
(2)、标配手机创建
package com.sb.design;
/***
* 标配手机创建
*/
public class StandardPhoneBuilder implements PhoneBuilder {
private Phone phone;
{
phone = new Phone();
}
@Override
public void setCpu() {
phone.setCpu("标准版");
}
@Override
public void setRam() {
phone.setRam("128G");
}
@Override
public void setPixel() {
phone.setPixel(10000);
}
@Override
public void setBattery() {
phone.setBattery(15000);
}
@Override
public Phone build() {
return phone;
}
}
4、指导者按照客户要求,指定具体的建造者、并按照建造者建造流程建造具体产品,这里只是指定了流程,而具体的建造操作是在具体建造者中完成。
package com.sb.design;
/**
* 表示、建造过程的隔离
*/
public class Directory {
private PhoneBuilder builder;
/**
* 具体建造者
*
* @param builder
*/
public Directory(PhoneBuilder builder) throws Exception {
this.builder = builder;
}
/**
* 建造流程、具体建造操作是在具体的建造者中完成
* 使用组装过程来比喻更贴切,具体的cpu、ram、等都是现成的,这里只是一个组装的过程
*/
public void create() {
//建造者设置,配置具体产品属性
builder.setCpu();
builder.setRam();
builder.setPixel();
builder.setBattery();
}
/**
* 获取产品、建造过程隐藏
*
* @return
*/
public Phone getProduct() {
return builder.build();
}
}
5、获取产品
//高配手机建造者
PhoneBuilder proBuilder = new ProPhoneBuilder();
//指导者(组装这)
Directory proDirectory = new Directory(proBuilder);
//按照用户需求组装
proDirectory.create();
//获取用户所需产品
Phone proPhone = proDirectory.getProduct();
System.out.println(proPhone.toString());
//标配
PhoneBuilder stdBuilder = new StandardPhoneBuilder();
Directory stdDirectory = new Directory(stdBuilder);
stdDirectory.create();
Phone stdPhone = stdDirectory.getProduct();
System.out.println(stdPhone.toString());
6、执行结果
处理器:加强版 内存:256G 像素:10000 电池容量:20000
处理器:标准版 内存:128G 像素:10000 电池容量:15000
三、为何使用建造者模式、在什么场景下使用
1、相比使用构造函数直接给对象变量赋值,使用setter、builder 这两种方式不用去看参数类型、顺序,使用起来方便。
2、具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响。
3、对象比较复杂的时候使用构造函数或setter来设置属性,容易丢失一些属性,而建造者模式能复用,可以有效避免这个问题。
四、演变后的建造者模式
演变后的建造者模式在平时项目中使用的很多,下来看看他的实现
1、产品定义、具体建造者定义、建造流程设置、具体建造操作实现
package com.sb.design;
/***
* 电脑产品
* 如果创建的对象属性不能修改,可以不设置setter方法
*/
public class Computer {
private String cpu;
private String memory;
private String disk;
/**
* 使用建造者创建,所以私有构造函数、不进行直接创建
*/
private Computer() {
}
/**
* 使用建造者创建,所以私有构造函数、不进行直接创建
*
* @param builder
*/
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.memory = builder.memory;
this.disk = builder.disk;
}
@Override
public String toString() {
return new StringBuffer().append("cpu:").append(cpu).append(" memory:").append(memory).append(" disk:")
.append(disk).toString();
}
/**
* 建造者
* 建造者属性和产品属性一致
*/
public static class Builder {
private String cpu;
private String memory;
private String disk;
/**
* 具体建造操作
*
* @param cpu
* @return
*/
public Builder cpu(String cpu) {
this.cpu = cpu;
return this;
}
/**
* 具体建造操作
*
* @param memory
* @return
*/
public Builder memory(String memory) {
this.memory = memory;
return this;
}
/**
* 具体建造操作
*
* @param disk
* @return
*/
public Builder disk(String disk) {
this.disk = disk;
return this;
}
/**
* 建造流程(组装操作)、并返回产品
*
* @return
*/
public Computer build() {
Computer computer = new Computer(this);
return computer;
}
}
}
2、产品定义、创建产品
Computer computerHigh = new Computer.Builder().cpu("i7").memory("32G").disk("1T固态盘").build();
Computer computerStd = new Computer.Builder().cpu("i7").memory("16G").disk("500固态盘").build();
System.out.println(computerHigh.toString());
System.out.println(computerStd.toString());
3、运行结果
cpu:i7 memory:32G disk:1T固态盘
cpu:i7 memory:16G disk:500固态盘
Process finished with exit code 0
五、演变后的建造者模式优缺点
优点
1、其实相比标准的(经典)建造者模式,这种演变后的建造者设计模式使用的更多,他同样隐藏了产品的建造过程、你只需要输入你需要的属性和值。
2、创建产品的时候还可以设置构造函数的私有化、只能按照构建者构建、还可以省略setter方法创建一个不能改变的对象;当然如果有必填属性还是定义为final来保证参数必填;使用灵活!
3、使用方便、可读性强、有逼格!
缺点
1、但是这种方式相比直接使用构造函数或setter来给对象赋值多了一个对象的创建,相对来说更耗资源。
建造者模式详解
804

被折叠的 条评论
为什么被折叠?



