软件设计模式白话文系列(五)建造者模式

1、描述

将一个对象的构造过程进行封装,并按照一定顺序进行构造。

通俗的讲,假如要创建电脑的对象,那么各个实例的属性不同,也就是电脑的配置各不相同.这个时候可以考虑用构造者模式。

2、适用性

当需要创建的对象创建过程复杂,如对象由多个部件构成,且各部件面临着复杂的变化。

3、实现逻辑

  • 产品类:需要创建的对象。
  • 抽象建造者类:封装构建步骤,定义产品对象的规范。
  • 具体建造者类:实现抽象建造者类,实现产品类的各个属性的具体方法。在构造过程完成后,提供产品的实例。
  • 指挥者类:调用具体建造者类来创建复杂对象的各个部分,负责保证对象各部分完整创建或按某种顺序创建。

4、实战代码

用建造者模式创建 RabbitMQ 客户端对象。

4.1 常规方式

/**
 * 产品类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-09 19:19:15
 */
@Setter
public class RabbitMQ {
    private String host;
    private int port;
    private int mode;
    private String exchange;
    private String queue;
    private boolean durable;
    private int connectionTimeout;

    public void sendMessage(String msg) {
        System.out.println("发送消息:" + msg);
    }
}

/**
 * 抽象建造者类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-09 19:17:04
 */
public abstract class Builder {
    protected RabbitMQ rabbitMQ= new RabbitMQ();

    public abstract void buildHost();
    public abstract void buildPort();
    public abstract void buildMode();
    public abstract void buildExchange();
    public abstract void buildQueue();
    public abstract void buildDurable();
    public abstract void buildConnectionTimeout();

    public abstract RabbitMQ createRabbitMQ();
}

/**
 * 具体建造者类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-09 19:42:11
 */
public class MQBuilder extends Builder {
    @Override
    public void buildHost() {
        rabbitMQ.setHost("127.0.0.1");
    }

    @Override
    public void buildPort() {
        rabbitMQ.setPort(5672);
    }

    @Override
    public void buildMode() {
        rabbitMQ.setMode(1);
    }

    @Override
    public void buildExchange() {
        rabbitMQ.setExchange("exchange");
    }

    @Override
    public void buildQueue() {
        rabbitMQ.setQueue("test");
    }

    @Override
    public void buildDurable() {
        rabbitMQ.setDurable(true);
    }

    @Override
    public void buildConnectionTimeout() {
        rabbitMQ.setConnectionTimeout(3000);
    }

    @Override
    public RabbitMQ createRabbitMQ() {
        return rabbitMQ;
    }

}

/**
 * 指挥者类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-09 19:55:33
 */
public class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public RabbitMQ construct() {
        builder.buildHost();
        builder.buildPort();
        builder.buildMode();
        builder.buildExchange();
        builder.buildDurable();
        builder.buildQueue();
        builder.buildConnectionTimeout();

        return builder.createRabbitMQ();
    }
}

/**
 * 测试类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-09 20:01:11
 */
public class Client {
    public static void main(String[] args) {
        MQBuilder mqBuilder = new MQBuilder();
        Director director = new Director(mqBuilder);
        RabbitMQ rabbitMQ = director.construct();
        rabbitMQ.sendMessage("测试对象");
    }
}

执行结果:

4.2 习惯性常用方式

上述常规方式中,我们需要每次都创建具体的构建类,这样产品类的每个属性都完全受具体构建类的控制,但是我们日常开发中,产品类的各个属性几乎都存在变化,所以可以这样优化:

/**
 * 习惯性构建者方式
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-09 20:50:27
 */
public class RabbitMQ {

    private RabbitMQ(Builder builder) {

    }

    public void sendMessage(String msg) {
        System.out.println("发送消息:" + msg);
    }

    public static final class Builder {
        private String host;
        private int port;
        private int mode;
        private String exchange;
        private String queue;
        private boolean durable;
        private int connectionTimeout;

        public Builder host(String host) {
            this.host = host;
            return this;
        }

        public Builder port(int port) {
            this.port = port;
            return this;
        }

        public Builder mode(int mode) {
            this.mode = mode;
            return this;
        }

        public Builder exchange(String exchange) {
            this.exchange = exchange;
            return this;
        }

        public Builder queue(String queue) {
            this.queue = queue;
            return this;
        }

        public Builder durable(boolean durable) {
            this.durable = durable;
            return this;
        }

        public Builder connectionTimeout(int connectionTimeout) {
            this.connectionTimeout = connectionTimeout;
            return this;
        }

        public RabbitMQ build() {
            return new RabbitMQ(this);
        }
    }

}

执行结果:

这种方式,摆脱了超⻓构造⽅法参数的束缚的同时也保护了不可变对象的密闭性。

4.3 lombok Builder 方式

可以利用 lombok 插件简化代码

/**
 * lombok Builder 方式
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-09 21:04:11
 */
@Builder
public class RabbitMQ {
    private String host;
    private int port;
    private int mode;
    private String exchange;
    private String queue;
    private boolean durable;
    private int connectionTimeout;
}

/**
 * 测试类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-09 20:01:11
 */
public class Client {
    public static void main(String[] args) {
        RabbitMQ rabbitMQ = RabbitMQ.builder()
                .host("127.0.0.1")
                .port(5462)
                .exchange("exchange")
                .durable(true)
                .mode(1)
                .queue("queue")
                .connectionTimeout(3000)
                .build();
        rabbitMQ.sendMessage("lombok Builder 方式");
    }
}

插件自动生成代码

public class RabbitMQ {
    private String host;
    private int port;
    private int mode;
    private String exchange;
    private String queue;
    private boolean durable;
    private int connectionTimeout;

    public void sendMessage(String msg) {
        System.out.println("发送消息:" + msg);
    }

    RabbitMQ(String host, int port, int mode, String exchange, String queue, boolean durable, int connectionTimeout) {
        this.host = host;
        this.port = port;
        this.mode = mode;
        this.exchange = exchange;
        this.queue = queue;
        this.durable = durable;
        this.connectionTimeout = connectionTimeout;
    }

    public static RabbitMQ.RabbitMQBuilder builder() {
        return new RabbitMQ.RabbitMQBuilder();
    }

    public static class RabbitMQBuilder {
        private String host;
        private int port;
        private int mode;
        private String exchange;
        private String queue;
        private boolean durable;
        private int connectionTimeout;

        RabbitMQBuilder() {
        }

        public RabbitMQ.RabbitMQBuilder host(String host) {
            this.host = host;
            return this;
        }

        public RabbitMQ.RabbitMQBuilder port(int port) {
            this.port = port;
            return this;
        }

        public RabbitMQ.RabbitMQBuilder mode(int mode) {
            this.mode = mode;
            return this;
        }

        public RabbitMQ.RabbitMQBuilder exchange(String exchange) {
            this.exchange = exchange;
            return this;
        }

        public RabbitMQ.RabbitMQBuilder queue(String queue) {
            this.queue = queue;
            return this;
        }

        public RabbitMQ.RabbitMQBuilder durable(boolean durable) {
            this.durable = durable;
            return this;
        }

        public RabbitMQ.RabbitMQBuilder connectionTimeout(int connectionTimeout) {
            this.connectionTimeout = connectionTimeout;
            return this;
        }

        public RabbitMQ build() {
            return new RabbitMQ(this.host, this.port, this.mode, this.exchange, this.queue, this.durable, this.connectionTimeout);
        }

        public String toString() {
            return "RabbitMQ.RabbitMQBuilder(host=" + this.host + ", port=" + this.port + ", mode=" + this.mode + ", exchange=" + this.exchange + ", queue=" + this.queue + ", durable=" + this.durable + ", connectionTimeout=" + this.connectionTimeout + ")";
        }
    }
}

执行结果: