new复杂对象问题
需求: 新建汽车对象,至少包含 大小、轮胎、装饰、发动机等等详细属性。最先想到的方式是直接new出对象。
代码实现
package com.example.pattern.builder;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author zjt
* @date 2020-12-11
* 汽车对象
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Car {
private Common common; // 通用属性
private Tire tire; // 轮胎
private Engine engine; // 发动机
private Decorate decorate; // 装饰
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Common {
private String color; // 颜色
private String model; // 型号
private double length; // 长
private double high; // 宽
private double width; // 高
// ......
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Tire {
private String size;
// ......
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Engine {
private String detail;
// ......
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Decorate {
private String seat;
// ......
}
public static void main(String[] args) {
Common common = new Common("白色", "V5", 5, 1.5, 2);
Tire tire = new Tire("40CM");
Engine engine = new Engine("8缸发动机");
Decorate decorate = new Decorate("普通座椅");
Car car = new Car(common, tire, engine, decorate);
System.out.println(car);
}
这种方式的优点是容易理解、程序结构简单。缺点是没有设计缓存层,程序的扩展和维护不好,这种设计方案,把产品和创建产品的过程封装在一起,耦合性增加。解决思路:将产品和产品的创建过程进行解耦->建造者模式。
建造者模式
基本介绍:
分离复杂对象的构建和表示,同样的构建过程可以创建不同的表示,
1、建造者模式也叫做生成器模式,是一种对象构建模式。将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现的对象。
2、建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的用户构建细节。
建造者模式的四个角色
1、Product(产品角色):一个具体的产品对象。
2、Builder(抽象建造者):创建一个Product对象的各个部件指定的接口/抽象类。
3、ConcreteBuilder(具体建造者):实现接口,构建和装配各个部件。
4、Director(指挥者):构建一个使用Builder接口的对象,它主要用户创建一个复杂的对象,它主要有两个作用,一:隔离了客户与对象的生产过程,二:负责控制产品对象的生产过程。
类图分析
变形之后代码实现
public interface CarBuilder { // 汽车构建器
// 返回 CarBuilder 原因是调用是方便,可以写出链式调用的结构
// 也可以返回 void 调用的时候会麻烦一点
CarBuilder buildCommon(); // 构建通用信息
CarBuilder buildTire(); // 构建轮胎信息
CarBuilder buildEngine(); // 构建发动机信息
CarBuilder buildDecorate(); // 构建装饰信息
Car build(); // 返回汽车对象
}
public class MineCar implements CarBuilder {
Car car = new Car();
@Override
public CarBuilder buildCommon() {
car.common = new Common("白色", "ZL", 5, 1.6, 2.1);
return this; // 返回当前对象
}
@Override
public CarBuilder buildTire() {
car.tire = new Tire("型号");
return this;
}
@Override
public CarBuilder buildEngine() {
car.engine = new Engine("8缸发动机");
return this;
}
@Override
public CarBuilder buildDecorate() {
car.decorate = new Decorate("真皮座椅");
return this;
}
@Override
public Car build() {
return car;
}
}
public class Client {
public static void main(String[] args) {
CarBuilder car = new MineCar();
// 指挥者可以省略 使用链式调用初始化对象
Car build = car.buildCommon()
.buildEngine()
.buildTire()
.buildDecorate()
.build();
System.out.println(build);
}
}
构建者模式使用此方法构建抽象出去,也可以变形一下使用,类似于工厂模式。
@Data
@AllArgsConstructor
public class Car {
public Common common; // 通用属性
public Tire tire; // 轮胎
public Engine engine; // 发动机
public Decorate decorate; // 装饰
// ......
private Car() { // 私有化构造器
}
public static class CarBuilder { // 内部静态类统一构建Car对象 类似于静态工厂
Car car = new Car();
public CarBuilder commonInfo(String color, String model, double length, double high, double width) {
car.common = new Common(color, model, length, high, width);
return this;
}
public CarBuilder tireInfo(String size) {
car.tire = new Tire(size);
return this;
}
public CarBuilder engineInfo(String detail) {
car.engine = new Engine(detail);
return this;
}
public CarBuilder decorateInfo(String seat) {
car.decorate = new Decorate(seat);
return this;
}
public Car build() {
return car;
}
}
}
Car car1 = new Car.CarBuilder()
.commonInfo("1", "1", 1, 1, 1)
.tireInfo("1")
.engineInfo("1")
//.decorateInfo("1") 用到的传入,用不到的不传值
.build();
System.out.println(car1);
建造者模式的注意事项和细节
1、客户端(使用程序)无需知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
2、每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
3、可以更加精细的控制产品的创建过程,将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方法使用程序来控制创建过程。
4、增加新的具体建造者无需修改原有类库的代码,指挥者针对抽象建造者类进行编程,系统扩展方便,符合开闭原则。
5、建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
6、如果产品的内部变化复杂,可能会导致需要定义很多的具体建造者来实现这种变化,导致系统代码变得庞大,因此在这种情况下需要考虑是否选择建造者模式。
7、抽象工厂模式与建造者模式:抽象工厂模式实现对产品家族的定义,一个产品家族是这样一系列的产品,具有不同分类维度的产品组合,采用抽象工厂模式不需要关心构建过程,只关心什么产品由什么工厂生产即可。建造者模式则要求按照指定的蓝图构建产品,它的主要目的是通过组装零配件而产生一个新的产品。