设计模式之建造者模式

什么是建造者模式

建造者模式(Builder Pattern) 又叫生成器模式,建造者模式可以将一个产品的内部表象与产品的生产过程抽象出来,从而可以使同一个建造过程生成具有不同的内部表象的产品对象。当用户使用的时候只需要指定建造对象的类型就可以得到该对象,而无须知道具体的实现细节。

造者模式中的四个角色

  1. Product(产品角色): 一个具体的产品对象;
  2. Builder(抽象建造者): 创建一个Product对象的各个部件指定的抽象接口;
  3. ConcreteBuilder(具体建造者): 实现抽象接口,构建和装配各个部件;
  4. Director(指挥者): 构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程;

优点

  1. 使用者无需知道产品的实现细节,将产品与产品的创建过程解耦,使得相同的过程可以创建不通的产品;
  2. 每个产品的建造者都是独立的,面对抽象编程,方便扩展,符合开闭原则
  3. 可以更加精细地控制产品的创建过程,将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程;

缺点

  1. 建造者模式一般用于创建有共同点的产品,当产品之间的差异很大时候,就不太适用了;
  2. 如果产品内部变化很复杂的话,这样就会产生很多建造者类,导致系统很庞大,不易于维护;

常见的应用场景

  1. Java中的StringBuilder;
  2. Lombok的Builder;

案例一

下面我就将使用建造者模式来抽象出一个汽车工厂可以分别建造奥迪和奔驰牌的汽车,不管是奔驰还是奥迪,它们都有发动机(Engine)、变速箱(Gearbox)、底盘(Chassis)等三大件,它们分别有自己的建造者类来控制自己的生产过程;

UML图

在这里插入图片描述

分别定义发动机(Engine)、变速箱(Gearbox)、底盘(Chassis)等三大件

public class Engine {

    private String name;

    public Engine(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Gearbox {

    private String name;

    public Gearbox(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Chassis {

    private String name;

    public Chassis(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

创建一个汽车类,有发动机(Engine)、变速箱(Gearbox)、底盘(Chassis)三个组件

public class Car {

    private Engine engine; // 发动机
    private Gearbox gearbox; // 变速箱
    private Chassis chassis; // 底盘

    public Engine getEngine() {
        return engine;
    }

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public Gearbox getGearbox() {
        return gearbox;
    }

    public void setGearbox(Gearbox gearbox) {
        this.gearbox = gearbox;
    }

    public Chassis getChassis() {
        return chassis;
    }

    public void setChassis(Chassis chassis) {
        this.chassis = chassis;
    }
}

定义一个汽车建造者抽象类,用来构建汽车组件

public abstract class CarBuilder {

    /**
     * 建造汽车发动机
     *
     * @return
     */
    public abstract void builderEngine();

    /**
     * 建造汽车变速箱
     *
     * @return
     */
    public abstract void builderGearbox();

    /**
     * 建造汽车底盘
     *
     * @return
     */
    public abstract void builderChassis();

    /**
     * 建造汽车
     *
     * @return
     */
    public abstract Car builderCar();
}

定义一个汽车组装接口,以及相应的实现类,来描述汽车的组装过程

public interface ICarDirectory {

    /**
     * 建造汽车
     *
     * @return
     */
    Car constructCar(CarBuilder builder);
}
public class CarDirectory implements ICarDirectory {

    @Override
    public Car constructCar(CarBuilder builder) {
        // 建造发动机
        builder.builderEngine();
        // 建造变速箱
        builder.builderGearbox();
        // 建造底盘
        builder.builderChassis();
        return builder.builderCar();
    }
}

分别定义奥迪建造者类和奔驰建造者类,装配各个组件

public class AudiCarBuilder extends CarBuilder {

    private Car car;

    public AudiCarBuilder(){
        this.car = new Car();
    }

    @Override
    public void builderEngine() {
        car.setEngine(new Engine("奥迪牌发动机"));
    }

    @Override
    public void builderGearbox() {
        car.setGearbox(new Gearbox("奥迪牌变速箱"));
    }

    @Override
    public void builderChassis() {
        car.setChassis(new Chassis("奥迪牌底盘"));
    }

    @Override
    public Car builderCar() {
        return car;
    }
}
public class BenzCarBuilder extends CarBuilder {

    private Car car;

    public BenzCarBuilder(){
        this.car = new Car();
    }

    @Override
    public void builderEngine() {
        car.setEngine(new Engine("奔驰牌发动机"));
    }

    @Override
    public void builderGearbox() {
        car.setGearbox(new Gearbox("奔驰牌变速箱"));
    }

    @Override
    public void builderChassis() {
        car.setChassis(new Chassis("奔驰牌底盘"));
    }

    @Override
    public Car builderCar() {
        return car;
    }
}

客户端使用:

public class Test {
    public static void main(String[] args) {
        ICarDirectory directory = new CarDirectory();

        Car benzCar = directory.constructCar(new BenzCarBuilder());
        System.out.println(benzCar.getEngine().getName());
        System.out.println(benzCar.getGearbox().getName());
        System.out.println(benzCar.getChassis().getName());

        Car audiCar = directory.constructCar(new AudiCarBuilder());
        System.out.println(audiCar.getEngine().getName());
        System.out.println(audiCar.getGearbox().getName());
        System.out.println(audiCar.getChassis().getName());
    }
}

这样我们就实现了相同的生产线,可以分别生产不同品牌的汽车产品

上面演示了建造者模式的常规用法,指挥者(Director)用来控制建造者(Builder)的生产过程,并返回建造的产品;

案例二

下面我来演示另外一种用法,就是当一个构造方法需要传入很多参数,创建找个对象实例的时候,很容易因为参数的位置,导致最终的数据有偏差,代码可读性也很差。这个时候我们就可以利用建造者模式进行代码重构,此处的演示使用Lombok的Builder组件也可达到相同的效果:

重构前
public class Person {
    private String name;
    private String age;
    private String sex;

    public Person(String name, String age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
}

public class Test {
    public static void main(String[] args) {
        Person person = new Person("小明","23","男");
    }
}
重构后
public class Person {
    private String name;
    private String age;
    private String sex;

    public Person(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.sex = builder.sex;
    }

    public static final class Builder {
        private String name;
        private String age;
        private String sex;

        public Builder() {}

        public Builder name(String val) {
            name = val;
            return this;
        }
        public Builder age(String val) {
            age = val;
            return this;
        }
        public Builder sex(String val) {
            sex = val;
            return this;
        }

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

public class Test {
    public static void main(String[] args) {
        Person person = new Person.Builder().name("小明").age("20").sex("男").build();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值