前言
生活中这样的例子很多,如游戏中的不同角色,其性别、个性、能力、脸型、体型、服装、发型等特性都有所差异;还有汽车中的方向盘、发动机、车架、轮胎等部件也多种多样;每封电子邮件的发件人、收件人、主题、内容、附件等内容也各不相同。
以上所有这些产品都是由多个部件构成的,各个部件可以灵活选择,但其创建步骤都大同小异。这类产品的创建无法用前面介绍的工厂模式描述,只有建造者模式可以很好地描述该类产品的创建。
定义
建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的
优点与缺点
优点
- 扩展性好,各个具体的建造者相互独立,有利于系统的解耦
缺点
- 产品的组成部分必须相同(类的属性值相同),这限制了其使用范围
模式的结构与实现
建造者(Builder)模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成
模式的结构
- 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
- 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()
- 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法
- 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息
结构图
代码实现
需求
客厅装修是一个复杂的过程,它包含墙体的装修、电视机的选择、沙发的购买与布局等。客户把装修要求告诉项目经理,项目经理指挥装修工人一步步装修,最后完成整个客厅的装修与布局,所以本实例用建造者模式实现比较适合。
这里客厅是产品,包括墙、电视和沙发等组成部分。具体装修工人是具体建造者,他们负责装修与墙、电视和沙发的布局。项目经理是指挥者,他负责指挥装修工人进行装修。
类与角色关系
类名 | 角色 |
---|---|
Worker | 抽象建造者 : 工人 |
WorkerOne | 具体建造者 : 工人1 |
WorkerTwo | 具体建造者 : 工人2 |
Parlour | 产品 : 客厅 |
ProjectManager | 指挥者 : 项目经理 |
代码
Worker
/**
*
* 抽象建造者 : 工人
*
* @author hanchao
* @version 1.0
* @date 2022/4/25 16:04
*/
public abstract class Worker {
public Parlour parlour = new Parlour();
public abstract void buildWall();
public abstract void buildTv();
public abstract void buildSofa();
public Parlour getResult(){
return parlour;
}
}
WorkerOne
/**
*
* 具体建造者 : 工人1
*
* @author hanchao
* @version 1.0
* @date 2022/4/25 16:07
*/
public class WorkerOne extends Worker {
@Override
public void buildWall() {
parlour.setWall("wall1");
}
@Override
public void buildTv() {
parlour.setTv("tv1");
}
@Override
public void buildSofa() {
parlour.setSofa("sofa1");
}
}
WorkerTwo
/**
*
* 具体建造者 : 工人2
*
* @author hanchao
* @version 1.0
* @date 2022/4/25 16:11
*/
public class WorkerTwo extends Worker {
@Override
public void buildWall() {
parlour.setWall("wall2");
}
@Override
public void buildTv() {
parlour.setTv("tv2");
}
@Override
public void buildSofa() {
parlour.setSofa("sofa2");
}
}
Parlour
/**
*
* 产品 : 客厅
*
* @author hanchao
* @version 1.0
* @date 2022/4/25 16:00
*/
public class Parlour {
private String wall;
private String tv;
private String sofa;
public String getWall() {
return wall;
}
public void setWall(String wall) {
this.wall = wall;
}
public String getTv() {
return tv;
}
public void setTv(String tv) {
this.tv = tv;
}
public String getSofa() {
return sofa;
}
public void setSofa(String sofa) {
this.sofa = sofa;
}
public void show(){
System.out.println("this.wall = " + this.wall);
System.out.println("this.tv = " + this.tv);
System.out.println("this.sofa = " + this.sofa);
}
}
ProjectManager
/**
*
* 指挥者 : 项目经理
*
* @author hanchao
* @version 1.0
* @date 2022/4/25 16:13
*/
public class ProjectManager {
public Worker worker;
public ProjectManager (Worker worker){
this.worker = worker;
}
public Parlour create(){
this.worker.buildWall();
this.worker.buildTv();
this.worker.buildSofa();
return worker.getResult();
}
}