建造者模式概念
任务:软件开发过程中,当遇到一个“复杂的对象”,该对象由好多部分组成,各个部分的组合比较稳定或有一定的依赖次序,但各部分自身却经常面临变化时,可以隔离出“复杂对象的各个部分”的变化,从而保证系统中“稳定结构算法”,这就是建造者模式的任务。建造者模式将复杂的内部创建封装,对于外部调用的人来说,只需要传入建造者和建造工具,对于内部是如何实现的,用户无需关心。
复杂对象是指那些包含了多个成员属性的对象,这些成员属性也叫作部件或零件。例如:汽车包含方向盘,轮胎,发动机等部件;电子邮件包含收件人,发件人,主题,内容,附件等部件。
构建者模式的结构
构建者模式一步一步的创建一个复杂的对象。构建者模式结构中包含四种角色。
- Builder(抽象建造者):可以是抽象类,也可以是对象。它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般指定两类方法,一类是BuildPartX(),用于创建复杂对象的各个部件;另一个是返回返回复杂对象的方法,getResult()方法。
- ConcreteBuilder(具体构建者):实现Builder接口,定义并明确它所创建的复杂对象,也可以提供一个方法,返回它所创建好的复杂产品对象。
- Product(产品角色):它是被构建的复杂对象,包含多个组成部分,具体建造者创造该产品的内部表示并定义它的装配过程。
- Director(指挥者):复杂安排复杂对象的建造次序。客户端将具体的建造者类型和具体的建造者对象通过反射机制或者配置文件传递给指挥者,指挥者用自己的建造方法construct()调用建造者对象的部件构造与装配方法,完成构建复杂对象的任务。
建造者模式与抽象工厂模式有点相似,但是建造者模式返回的是一个完整的复杂产品,而抽象工厂模式返回的是一系列相关的产品;抽象工厂模式中,客户端通过选择具体的工厂来生成所需对象,而建造者模式中,客户端通过指定具体的建造者类型并指导Director类如何去生成对象,然后将其结果返回。
如果将抽象工厂模式看成一个汽车配件生产厂,生成不同类型的汽车配置,那么建造者模式就是一个汽车组装厂,通过对器件进行组装,返回一辆完整的汽车
建造者模式演示代码
/**
* 建造者接口
*/
public interface Builder {
void buildPartA();
void buildPartB();
void buildPartC();
Product getResult();
}
/**
* 具体建造者
*/
class ConcreteBuilder implements Builder{
Part partA, partB, partC;
@Override
public void buildPartA() {
//创建partA
}
@Override
public void buildPartB() {
//创建partB
}
@Override
public void buildPartC() {
//创建partC
}
@Override
public Product getResult() {
return null;//返回最后的组装结果
}
}
/**
* 指挥者类
*/
class Director{
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void construct(){
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
/**
* 客户端
*/
class Client{
public static void main(String[] args){
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
Product product = builder.getResult();
}
}
interface Part{}
interface Product{}
举例说明
假如一家电脑加工厂要组装一台笔记本电脑,电脑由CPU,主板,显示器等构成,基本组装步骤为:1.组装CPU;2.组装主板;3.组装显示器,最终组装成的产品是一台ThinkPad。
/**
* 电脑类:不管是联想还是方正电脑,都包含这些部件
*/
class Computer{
private String board;//主板
private String cpu;//CPU
private String monitor;//显示器
//省略get、set方法
}
/**
* 建造电脑的抽象类
*/
public abstract class ComputerBuilder {
public abstract void buildBoard();
public abstract void buildCPU();
public abstract void buildMonitor();
public abstract Computer getCompuer();
}
/**
* ThinkPad建造类
*/
class ThinkPadBuilder extends ComputerBuilder{
Computer computer = new Computer();
@Override
public void buildBoard() {
computer.setBoard("ThinkPad主板");
}
@Override
public void buildCPU() {
computer.setCpu("ThinkPadCPU");
}
@Override
public void buildMonitor() {
computer.setMonitor("ThinkPad显示器");
}
@Override
public Computer getCompuer() {
return computer;
}
}
/**
* 电脑组装操作的封装类
*/
class ComputerDirector{
public void constructComputer(ComputerBuilder builder){
builder.buildBoard();
builder.buildCPU();
builder.buildMonitor();
}
}
/**
* 客户端
*/
class UserClient{
public static void main(String[] args){
ComputerDirector computerDirector = new ComputerDirector();
// 创建ThinkPad生成器(工厂)
ComputerBuilder builder = new ThinkPadBuilder();
//调用ComputerDirector组装电脑
computerDirector.constructComputer(builder);
//得到组装好的电脑
Computer computer = builder.getCompuer();
System.out.println(computer.getBoard());
System.out.println(computer.getCpu());
System.out.println(computer.getMonitor());
}
}
控制台输出结果
ThinkPad主板
ThinkPadCPU
ThinkPad显示器
Process finished with exit code 0
建造者模式的优点
- 封装性:客户端不必知道产品内部组成细节
- 建造者独立,容易扩展:例如组装联想电脑和方正电脑,客户端只需要更改具体的建造者
- 便于控制细节,具体的建造者是独立的,方便对建造者细节逐步细化而不影响其他模块
建造者模式使用场景
- 相同的方法,不同的执行顺序,产生不同的事件结果时可以使用
- 产品类非常复杂,或者产品类的调用顺序不同而产生不同的效能
- 对象的创建过程中会使用系统中其他一些对象