【Java设计模式】五、建造者模式

文章目录

1、建造者模式

  • 某个对象的构建复杂
  • 将复杂的对象的创建 和 属性赋值所分离,使得同样的构建过程可以创建不同的表示
  • 建造的过程和细节调用者不需要知道,只需要通过构建者去进行操作

如,主机这个负责对象的构建,分离承诺内存条、主板这些部件,再组装构建。内存条替换一个别的,出来就是一个不同的对象。

建造者模式相关角色:

  • 产品类:复杂对象,主机
  • 抽象建造者类Builder:规定要实现复杂对象的哪些部件的创建
  • 具体建造者类ConcreteBuilder:实现Builder,完成各个部件的具体创建
  • 指挥者类Director:保证对象的各个部分按照某种顺序创建

2、案例:共享单车的创建

摩拜单车和ofo单车。Bike是产品,包含车架,车座等组件;Builder是抽象建造者,MobikeBuilder和OfoBuilder是具体的建造者,Director是指挥者。

具体的代码如下:

java 复制代码
//自行车类
@Data
public class Bike {
    private String frame;  //车架
    private String seat;   //座椅


}

抽象构建者Builder定义哪些部分要构建:

java 复制代码
// 抽象 builder 类
public abstract class Builder {

    protected Bike mBike = new Bike();

    public abstract void buildFrame();   //构建车架
    public abstract void buildSeat();    //构建座椅
    public abstract Bike createBike();   //构建自行车
    
}

写具体的构建者:

java 复制代码
//摩拜单车Builder类
public class MobikeBuilder extends Builder {

    @Override
    public void buildFrame() {
        mBike.setFrame("铝合金车架");
    }

    @Override
    public void buildSeat() {
        mBike.setSeat("真皮车座");
    }

    @Override
    public Bike createBike() {
        return mBike;
    }
}
java 复制代码
//ofo单车Builder类
public class OfoBuilder extends Builder {

    @Override
    public void buildFrame() {
        mBike.setFrame("碳纤维车架");
    }

    @Override
    public void buildSeat() {
        mBike.setSeat("橡胶车座");
    }

    @Override
    public Bike createBike() {
        return mBike;
    }
}

指挥者类:

java 复制代码
//指挥者类
public class Director {
    private Builder mBuilder;   //声明Builder类型的变量

    public Director(Builder builder) {
        mBuilder = builder;
    }
	
	//组装自行车的方法
    public Bike construct() {
        mBuilder.buildFrame();
        mBuilder.buildSeat();
        return mBuilder.createBike();
    }
}

客户端测试:

java 复制代码
public class Client {
    public static void main(String[] args) {
        showBike(new OfoBuilder());
        showBike(new MobikeBuilder());
    }
    private static void showBike(Builder builder) {
        Director director = new Director(builder);   //创建指挥者
        Bike bike = director.construct();   //让指挥者指挥组装
        System.out.println(bike.getFrame());
        System.out.println(bike.getSeat());
    }
}

再有新的单车公司加入,只需实现一个新的建造者类即可,符合开闭原则。但如果创建的产品组成部分差异很大,则不适合用建造者模式,比如要再造个电脑对象。

3、其他用途

java 复制代码
@Setter
@Getter
public class Phone {
    private String cpu;
    private String screen;
    private String memory;
    private String mainboard;

    public Phone(String cpu, String screen, String memory, String mainboard) {
        this.cpu = cpu;
        this.screen = screen;
        this.memory = memory;
        this.mainboard = mainboard;
    }
}

对于属性多的对象,创建其对象往往可读性很差,如:

java 复制代码
//构建Phone对象
Phone phone = new Phone("intel","三星屏幕","金士顿","华硕");

重构一下(@Builder注解的思路):

java 复制代码
public class Phone {

    private String cpu;
    private String screen;
    private String memory;
    private String mainboard;
	
	//私有的构造方法
    private Phone(Builder builder) {
        cpu = builder.cpu;
        screen = builder.screen;
        memory = builder.memory;
        mainboard = builder.mainboard;
    }

    public static final class Builder {
        private String cpu;
        private String screen;
        private String memory;
        private String mainboard;

        public Builder() {}

        public Builder cpu(String val) {
            cpu = val;
            return this;
        }
        public Builder screen(String val) {
            screen = val;
            return this;
        }
        public Builder memory(String val) {
            memory = val;
            return this;
        }
        public Builder mainboard(String val) {
            mainboard = val;
            return this;
        }
        //!!!!!
        public Phone build() {
            return new Phone(this);
         }
    }
    @Override
    public String toString() {
        return "Phone{" +
                "cpu='" + cpu + '\'' +
                ", screen='" + screen + '\'' +
                ", memory='" + memory + '\'' +
                ", mainboard='" + mainboard + '\'' +
                '}';
    }
}

此时就可链式编程创建这个对象(new Phone.Builder()创建静态内部类对象):

java 复制代码
public class Client {
    public static void main(String[] args) {
        Phone phone = new Phone.Builder()
                .cpu("intel")
                .mainboard("华硕主板")
                .memory("金士顿内存")
                .screen("三星屏幕")
                .build();
        System.out.println(phone);
    }
}
相关推荐
文丑颜不良啊41 分钟前
LeetCode2021~2040题目解析
java·leetcode
bksczm1 小时前
InnoDB 行格式详解:DYNAMIC / COMPACT / COMPRESSED / REDUNDANT
java·开发语言·数据库
liangbo71 小时前
Spring系列03:Bean 的三种注册方式
java·spring
余槐i2 小时前
MySQL 8.0 联合索引走错:为什么加了索引查询反而从 200ms 变成 8s
java·spring boot·mysql·docker·性能优化
SL_staff2 小时前
制造业订单交付总在最后一刻爆雷?用结构化计划模板打通跨系统协同断点
java·开源·全栈
做科研的周师兄2 小时前
【R语言实战】MixSIAR 氢氧同位素水源解析全流程:从混合空间校验到贝叶斯 MCMC 收敛诊断(后附完整代码)
java·大数据·开发语言
有点小困9772 小时前
Spring Boot 异步任务 ClassLoader 踩坑实录:ClassNotFoundException 的诡异真相
java
aiks_yuan2 小时前
Java 正则表达式很慢怎么办:Pattern 预编译只快 2~5 倍,真正卡死线程的是回溯(JDK 8、11、17 实测)
java
用户3721574261352 小时前
C# 填写 PDF 交互式表单:文本框、复选框、单选按钮和下拉列表
java
IT枫斗者枫哥2 小时前
Java 退款请求超时,先查原单还是重试?
java·后端