设计模式(二):建造者模式

拓朴潮涌
• 阅读 2407

Builder(建造者模式)

对一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

其实建造者模式在项目中进场能够看到,比如在Android中我们使用AlertDialog的时候

    AlertDialog.Builder builder =
          new AlertDialog.Builder(context)
                         .setIcon(R.mipmap.ic_launcher)
                         .setTitle("This is title")
                         .setMessage("This is Message")
                         .setPositiveButton("ok", null)
                         .create();
    builder.show();

类似的还有很多的库都使用了这种建造者模式,可以见的学习这种模式的必要性了

Builder(建造者模式)的UML类图

设计模式(二):建造者模式

其中:

  • Builder类 : 是抽象类,用来规范子类的组建

  • ConcreteBuilder类 : 是Builder的具体实现类

  • Director类 : 用于将产品同一组装

下面来看一下例子,如何实现一个简单的Builder

建造者模式的简单实现

以构建一辆车为例,一辆车大体上是有车牌,颜色,车的标牌等构成

首先创建构建着接口

public interface Builder {

    // 构建车的颜色
    void buildColor(String color);

    // 构建车的车牌
    void buildLicensePlate(String licensePlate);

    // 构建车的商标
    void buildBrand(String brand);

    // 构建完成最终的汽车
    Car build();
}

然后创建汽车产品类

public class Car {

    private String color;
    private String licensePlate;
    private String brand;

    public void setColor(String color) {
        this.color = color;
    }

    public void setLicensePlate(String licensePlate) {
        this.licensePlate = licensePlate;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    @Override
    public String toString() {
        return "Car{" +
                "color='" + color + '\'' +
                ", licensePlate='" + licensePlate + '\'' +
                ", brand='" + brand + '\'' +
                '}';
    }
}

然后创建汽车构建实现类

public class CarBuilder implements Builder {

    Car car;

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

    @Override
    public void buildColor(String color) {
        car.setColor(color);
    }

    @Override
    public void buildLicensePlate(String licensePlate) {
        car.setLicensePlate(licensePlate);
    }

    @Override
    public void buildBrand(String brand) {
        car.setBrand(brand);
    }

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

最后创建产品组装类

public class Director {

    Builder builder;

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

    public void construct(String color, String licensePlate, String brand) {
        builder.buildColor(color);
        builder.buildLicensePlate(licensePlate);
        builder.buildBrand(brand);
    }
}

一个简单的Builder构建者就完成了,我们来测试一下

Builder builder = new CarBuilder();
Director director =new Director(builder);
director.construct("red", "A88888", "Ferrari");
System.out.println(builder.build().toString());

输出结果:

Car{color='red', licensePlate='A88888', brand='Ferrari'}

一俩车牌号为A88888的红色法拉利就做完了!

但是为什么不是链式调用呢?

如果需要链式调用的话就需要对代码做一下修改

比如这里要创建一辆Ferrari

我们先创建一个Ferrari类,并且创建一个Builder内部类

具体代码如下:

public class Ferrari {

    private String color;
    private String licensePlate;
    private String brand;

    public void setColor(String color) {
        this.color = color;
    }

    public void setLicensePlate(String licensePlate) {
        this.licensePlate = licensePlate;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public static class Builder{

        Ferrari ferrari;

        public Builder(){
            ferrari = new Ferrari();
        }

        public Builder setColor(String color){
            ferrari.setColor(color);
            return this;
        }

        public Builder setLicensePlate(String licensePlate) {
            ferrari.setLicensePlate(licensePlate);
            return this;
        }

        public Builder setBrand(String brand){
            ferrari.setBrand(brand);
            return this;
        }

        public Ferrari build(){
            return ferrari;
        }

    }

    @Override
    public String toString() {
        return "Car{" +
                "color='" + color + '\'' +
                ", licensePlate='" + licensePlate + '\'' +
                ", brand='" + brand + '\'' +
                '}';
    }

}

测试一下

 // Call Chaining
Ferrari ferrari = new Ferrari.Builder()
        .setBrand("Ferrari")
        .setColor("Red")
        .setLicensePlate("B88888")
        .build();
System.out.println(ferrari.toString());

输出结果:

Car{color='Red', licensePlate='B88888', brand='Ferrari'}

其实,关于链式调用还有另一种写法,

这里创建一个Audi类,同样为其创建Builder内部类

public class Audi {

    private String color;
    private String licensePlate;
    private String brand;

    public static class Builder {

        private String color;
        private String licensePlate;
        private String brand;

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

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

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

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

    private Audi(Builder builder) {
        color = builder.color;
        licensePlate = builder.licensePlate;
        brand = builder.brand;
    }

    @Override
    public String toString() {
        return "Car{" +
                "color='" + color + '\'' +
                ", licensePlate='" + licensePlate + '\'' +
                ", brand='" + brand + '\'' +
                '}';
    }
}

在这里没有在Builder内部调用外部的setter方法,而是直接在内部类中初始化数据,然后在build之后再传递给私有构造函数,但是这里要注意,因为已经显示的写了一个构造函数,那么系统就不会为我们创建无参的共有构造函数,但是好处就是强制使用了构建者模式构建实例对象

同时,这种写法也是在《Effective Java》 中提倡的写法

使用方法跟之前的一样,输出结果也没有什么区别,读者可以自行尝试

具体使用哪一种写法,视实际情况而定


总结

关于构建者模式:

优点 具有良好的封装性,容易扩展

缺点 会产生多余的Builder对象,消耗内存


源码地址

更多内容

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java实现23种设计模式之责任链模式
顾名思义,责任链模式(ChainofResponsibilityPattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。pa
Wesley13 Wesley13
3年前
java游戏服务器 建造者模式
!(https://oscimg.oschina.net/oscnet/3b58bc7ab4dc4dedc9f0f10f0919a6987f4.jpg)这里的具体的建造者ConcreteBuilder可以多个这里我们以建造汽车为例:假设汽车需要:方向盘、汽车壳、还有四个轮子 这三样才能跑起来如果你因为粗心漏了其
Wesley13 Wesley13
3年前
Java设计模式之三种工厂模式
工厂模式实现了创建者和调用者的分离,实现了更好的解耦。详细分类:1)简单工厂模式(静态工厂模式);2)工厂方法模式;3)抽象工厂模式面向对象设计的基本原则:1)      OCP(开闭原则,OpenClosedPrinciple):一个软件的实体应当对扩展开放,对修改关闭。2)      
Stella981 Stella981
3年前
Python 设计模式之建造者模式 Builder Pattern
 引入建造者模式肯德基的菜单上有薯条,鸡腿,鸡翅,鸡米花,可乐,橙汁,火腿汉堡,至尊虾汉堡,牛肉汉堡,鸡肉卷等这些单品,也有很多套餐。比如套餐1:鸡翅,至尊虾汉堡,可乐,薯条套餐2:鸡腿,火腿汉堡,橙汁,薯条套餐3:。。。。。全家桶:。。。。。这种有各种各样的单品一步一步生成各种套餐,这种过程称的
Wesley13 Wesley13
3年前
Java进阶篇设计模式之三
前言在上一篇(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.cnblogs.com%2Fxuwujing%2Fp%2F9363142.html)中我们学习了工厂模式,介绍了简单工厂模式、工厂方法和抽象工厂模式。本篇则介绍设计模式中属于创建型模式的建造者模式和原型模式。
Wesley13 Wesley13
3年前
Java中23种设计模式详解
Java中23种设计模式1\.设计模式31.1创建型模式41.1.1工厂方法41.1.2抽象工厂61.1.3建造者模式101.1.4单态模式131.1.5原型模式151.2结构型模式171.2.1适配器模式171.2.2桥接模式191.2.3组合
Wesley13 Wesley13
3年前
Java设计模式之责任链模式
引入责任链模式责任链模式顾名思义,责任链模式(ChainofResponsibilityPattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会
Wesley13 Wesley13
3年前
Java Design Patterns
java的设计模式大体上分为三大类:创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模
Wesley13 Wesley13
3年前
C#设计模式 —— 工厂模式
。  工厂模式同样是项目中最常用的设计模式,工厂模式中又分为简单工厂,工厂方法,抽象工厂。下面我们由简单的开始逐一介绍。1.简单工厂模式  简单工厂又被称为静态工厂,在设计模式中属于创建型模式。主要解决的问题是封装了实例化的过程,通过传入参数来获不同实例。下面我们举一个项目中可能会用到的例子。  假设我们程序的数据保存在几个不同
Wesley13 Wesley13
3年前
Java描述设计模式(06):建造者模式
一、生活场景基于建造者模式,描述软件开发的流程。1、代码实现/基于建造者模式描述软件开发/publicclassC01_InScene{publicstaticvoidmain(Stringargs){B
Wesley13 Wesley13
3年前
23种设计模式(面向对象语言)
一、设计模式的分类总体来说设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。创建型模式是用来创建对象的模式,抽象了实例化的过程,帮助一个系统独立于其他关联对象的创建、组合和表示方式。所有的创建型模式都有两个主要功能:  1.将系统所使用的具体类的信息封装起来  2.隐藏