简介
在软件开发中,存在大量复杂对象,它们拥有一系列成员属性,这些成员属性中有些是引用类型的成员对象。而且在这些复杂对象中,还可能存在一些限制条件,如某些属性没有赋值则复杂对象不能作为一个完整的产品使用;有些属性的赋值必须按照某个顺序,一个属性没有赋值之前,另一个属性可能无法赋值等。
由于组合部件的过程很复杂,因此,这些部件的组合过程往往被“外部化”到一个称作建造者的对象里,建造者返还给客户端的是一个已经建造完毕的完整产品对象,而用户无须关心该对象所包含的属性以及它们的组装方式,这就是建造者模式的模式动机。
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
实例
建造者模式包含如下角色:
-
Builder
:抽象建造者 -
ConcreteBuilder
:具体建造者 -
Director
:指挥者 -
Product
:产品
电脑是每个程序员的标配,主要配件有:CPU、主板、内存、显卡、电源。当前主要有两大平台:AMD
和 Intel
,但是两个平台的一些零件是不一样的。所以肥宅在组装两个平台时选择的配件也是不一样的。
产品(电脑):
public class Computer {
/**
* cpu
*/
private String cpu;
/**
* 主板
*/
private String motherboar;
/**
* 内存
*/
private String ram;
/**
* 显卡
*/
private String graphicsCard;
/**
* 电源
*/
private String power;
//setter and getter
// toString
}
抽象工厂:
abstract class AbstractComputerBuilder {
/**
* 选择CPU
*/
abstract void buildCPU();
/**
* 选择主板
*/
abstract void buildMotherboar();
/**
* 选择内存
*/
abstract void buildRam();
/**
* 选择显卡
*/
abstract void buildGraphicsCard();
/**
* 选择电源
*/
abstract void buildPower();
/**
* 获取电脑
*/
abstract Computer getComputer();
}
具体建造者:
// AMD电脑 建造者
public class AmdComputerBuilder extends AbstractComputerBuilder {
private Computer computer = new Computer();
@Override
void buildCPU() {
computer.setCpu("2700x");
}
@Override
void buildMotherboar() {
computer.setMotherboar("华硕 ROG X470");
}
@Override
void buildRam() {
computer.setRam("芝奇 DDR4 8G");
}
@Override
void buildGraphicsCard() {
computer.setGraphicsCard("vega 56");
}
@Override
void buildPower() {
computer.setPower("EVGA 750W");
}
@Override
Computer getComputer() {
return computer;
}
}
// Intel 电脑建造者
public class IntelComputerBuilder extends AbstractComputerBuilder {
private Computer computer = new Computer();
@Override
void buildCPU() {
computer.setCpu("i7 8700");
}
@Override
void buildMotherboar() {
computer.setMotherboar("微星 Z370");
}
@Override
void buildRam() {
computer.setRam("金士顿 DDR4 8G");
}
@Override
void buildGraphicsCard() {
computer.setGraphicsCard("GTX 1080Ti");
}
@Override
void buildPower() {
computer.setPower("海韵 750W");
}
@Override
Computer getComputer() {
return computer;
}
}
指挥者:
public class ComputerDirector {
public void construct(AbstractComputerBuilder builder) {
builder.buildCPU();
builder.buildMotherboar();
builder.buildRam();
builder.buildGraphicsCard();
builder.buildPower();
}
}
测试:
public class Fz {
@Test
public void build() {
ComputerDirector director = new ComputerDirector();
AmdComputerBuilder amdComputerBuilder = new AmdComputerBuilder();
director.construct(amdComputerBuilder);
Computer amdComputer = amdComputerBuilder.getComputer();
System.out.println("选择AMD平台配件:" + amdComputer);
IntelComputerBuilder intelComputerBuilder = new IntelComputerBuilder();
director.construct(intelComputerBuilder);
Computer intelComputer = intelComputerBuilder.getComputer();
System.out.println("选择Intel平台配件:" + intelComputer);
}
}
类图
优点
- 建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。
- 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
- 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
- 建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。符合开闭原则。
缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
适用场景
在以下情况下可以使用建造者模式:
- 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
- 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
- 对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类中。
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
总结
建造者模式与工厂模式类似,适用的场景也很相似。建造者模式仅仅只比工厂模式多了一个”指挥者”的角色。在建造者模式的类图中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。
建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。建造者模式更加关注与零件装配的顺序。
一般来说,如果产品的建造很复杂,那么请用工厂模式;如果产品的建造更复杂,那么请用建造者模式。
最后
大家觉得不错可以点个赞在关注下,以后还会分享更多文章!同时我的的专栏:Java架构技术栈,以后还会分享更多文章!
网友评论