建造者模式的介绍
将一个复杂对象的构建与它的表示分离,使得同样的过程可以建造不同的表示。该模式属于创建型模式。本质上该模式就是一个对象的创建不是该类自己进行创建而是通过其他类进行创建。
建造者模式参与角色
参与角色 | 功能 |
---|---|
产品(Product) | 是一个被构建的对象,其构建过程在具体建造者中实现 |
建造者(builder) | 是具体建造者抽象或接口,内部是复杂产品的构建方法,但本身并不实现相关功能 |
具体建造者(ConcreteBuilder) | 实现建造者的的相关功能,用于对产品进行构建,具体化复杂对象各部分的创建 |
指挥者(director) | 指挥建造的具体流程,在内部持有一个建造者的引用,并实现了建造一个产品的流程 |
建造者模式UML
相关案例
在小明的表哥帮助小明组装好电脑后,小明的两个同学小红和小王也想让他的表哥帮他们组装电脑,他们把他们组装的电脑组件都给了小明,他们组装电脑的配件是不一致的。下面我们将使用建造者模式来实现这个案例。
案例分析
分析题目我们可以知道需求为获得两台组装好的电脑,我们需要使用建造者模式来实现。
使用建造者模式我们来划分四个角色
- 产品(product):电脑,我们需要定义一个电脑类,在内部有组装电脑的各种 方法。
- 建造者(builder):定义一个组装各个配件的抽象方法。
- 具体建造者:有两个,一个是构建小红电脑的构建者,一个是构建小王电脑的构建者;相同点是他们的内部都是实现了建造者类的方法,不同点是组装电脑的配件不一致(就是内部细节不一致)。
- 指挥者(director):表哥,他决定了电脑如何装配,在这里我们需要定义一个表哥类,在内部持有一个建造者引用,并且拥有一个决定装配电脑流程的方法。(注意在指挥者角色中建造的步骤是可以更改,这为程序提供了比较大的灵活性)
在分析完全部角色后我们可以开始具体的设计所需的类以及各个类所需的功能。
将外观模式和建造者模式进行比较:
(1)功能不一样,在建造者模式中我们创建的是一个对象,在外观模式中我们是把多个复杂的子系统的使用进行简化,合并。
(2)目的不一样。在建造者模式中我们是想将一个复杂对象的构建和表示分开,这样当我们对复杂对象进行维护的时候会比较简单;在外观模式中我们是希望在复杂的系统环境中将系统的使用变得更为简单,这样可以减少类之间的耦合性。
案例实现
产品角色代码
package builder.pattern;
import java.util.LinkedList;
import java.util.List;
/**
* @Introduction 该类是一个产品角色,内部包含,组装电脑的方法
*/
public class Product {
private List<String> assemble=new LinkedList<String>();
/**组装部件,在这里我们可以在具体构造类中调用该方法来表示装配了什么部件*/
public void assemblePart(String name) {
assemble.add(name);
}
/**展示装配的部件,为了展示效果,在真正的实际中这个不需要*/
public void show() {
for(String s:assemble) {
System.out.println(s);
}
}
}
建造者角色
package builder.pattern;
/**
* @Introduction 该类所扮演的角色是Builder角色内部含有创建一个Product的所有方法,但不实现
*/
public abstract class Builder {
public abstract void assembleCpu(); //装配Cpu
public abstract void assembleZhuBan(); //装配主板
public abstract void assembleNeiCun(); //装配内存
public abstract Product getResult();
}
具体建造者角色
(1)组装小红电脑
package builder.pattern;
/**
* @Introduction 该类所扮演的角色是具体建造者,继承了Builder抽象类,实现了为小红构建的电脑的所有需要模块
*/
public class BuilderXiaoHong extends Builder{
private Product xiaoHong=new Product(); //内部持有一个Product对象
/**实现了建造方法,这里这是实现了产品的模块的构建,并未将产品进行组装,也就是在真正执行的时候我们可以先装Cpu,然后在装主板
* ;但也可以先装主板,再装Cpu*/
@Override
public void assembleCpu() {
xiaoHong.assemblePart("为小红电脑装Cpu");
}
@Override
public void assembleZhuBan() {
xiaoHong.assemblePart("为小红电脑装主板");
}
@Override
public void assembleNeiCun() {
xiaoHong.assemblePart("为小红电脑装内存");
}
/**将创建好的角色返回(但不是直接返回,而是在经过指挥者之后再返回Product*/
@Override
public Product getResult() {
return xiaoHong;
}
}
(2)组装小王电脑
package builder.pattern;
/**
* @Introduction 该类所扮演的角色是具体建造者,实现了Builder类,用于实现小明电脑组装的各个具体的步骤,但不进行组装
*/
public class BuilderXiaoWang extends Builder{
private Product xiaoWang=new Product(); //内部持有一个Product对象
/**实现了建造方法,这里这是实现了产品的模块的构建,并未将产品进行组装,也就是在真正执行的时候我们可以先装Cpu,然后在装主板
* ;但也可以先装主板,再装Cpu*/
@Override
public void assembleCpu() {
xiaoWang.assemblePart("为小王红电脑装Cpu");
}
@Override
public void assembleZhuBan() {
xiaoWang.assemblePart("为小王红电脑装主板");
}
@Override
public void assembleNeiCun() {
xiaoWang.assemblePart("为小王红电脑装内存");
}
/**将创建好的角色返回(但不是直接返回,而是在经过指挥者之后再返回Product*/
@Override
public Product getResult() {
return xiaoWang;
}
}
指挥者角色
package builder.pattern;
/**
* @Introduction 该类扮演的角色是指挥者,作用为将具体建造者中的方法按照用户定义的规则进行组装。就如同在做菜是我们需要装盘、放盐
* 翻炒菜一样,在了解我们需要做什么之后,我们需要了解怎么去做,做一道菜的顺序是什么,将刚刚的动作按照炒菜的顺序去执行。
*
*/
public class BiaoGe {
/**进行指挥,按照一定的顺序去执行Builder中对应的操作(第一种组装顺序)*/
public void constructOne(Builder computer) {
computer.assembleCpu(); //先组装Cpu
computer.assembleNeiCun(); //再组装内存
computer.assembleZhuBan(); //最后组装主板
}
/**第二种组装顺序*/
public void constructTwoOne(Builder computer) {
computer.assembleNeiCun(); //先组装内存
computer.assembleCpu(); //再先组装Cpu
computer.assembleZhuBan(); //最后组装主板
}
}
用户界面模拟
package builder.pattern;
/**
1. @Introduction 该类是模拟用户对相关产品进行创建的过程
2. */
public class UserIn {
public static void main(String[] args) {
Builder builder; //所有具体构造者非一个抽象接口
Product computer;
BiaoGe biaoge=new BiaoGe(); //指挥Builder构建出相应computer
/**组装小红的电脑*/
builder=new BuilderXiaoHong(); //实现产品的各个部件的构建
biaoge.constructOne(builder); //将产品的各个部件进行组合执行,产生出一个真正的产品
computer=builder.getResult(); //将建造好的对象实例返回(实现了复杂对象的构建和表示分离)
computer.show();
/**组装小王的电脑*/
builder=new BuilderXiaoWang();
biaoge.constructOne(builder);
computer=builder.getResult();
computer.show();
}
}
运行结果如下
建造者模式优缺点
优点:
- 提高了系统的可拓展性和可维护性,在建造者模式中将复杂对象的创建和表示进行了分离,同时使用了指挥者提高了复杂对象的灵活性,可以对复杂产品的细节进行较好的控制。
- 实现了细节依赖于抽象,可以是相同的构建过程得到不同产品。
缺点:
如果产品的具体构造者很多,这无疑会使得系统变得更加庞大,提高了系统的复杂度。
建造者模式适用场景
(1)需要创建的对象内部结构比较复杂,需要将对象的构建和表象分离。
(2)需要相同的构建过程可以获得不同的产品。
来源:CSDN
作者:风起水涌
链接:https://blog.csdn.net/qq_41904978/article/details/103465942