美文网首页
设计模式学习笔记----建造者

设计模式学习笔记----建造者

作者: ssochi | 来源:发表于2019-06-17 15:57 被阅读0次

Builder建造者

建造者模式能解决复杂的产品生产过程,并且同工厂一样,能将生产内部逻辑与用户之间解耦。当然若要解决用户与建造者之间的耦合问题,则应该使用抽象建造者,与抽象工厂类似。

使用场景

使用建造者模式,意味着你生成的产品比较复杂,它不仅拥有很多参数需要配置,并且有很多可选项。当使用传统的构建函数或者工厂模式时,我们需要用很长的构造函数来指定必须的参数,并且,对于可选的参数,每增加一个参数,便需要增加一个构造函数。(对于可选参数这点,仅局限与Java这种构造函数不支持默认值的语言)
同样当你的产品的生成过程非常复杂,存在很多种可能性,需要用户来规定初始化步骤,但又不想将初始化的具体暴露给用户时,建造者模式也是不错的选择。

实现

假象一个场景,公司生成一种方形的盒子,盒子有长宽高,价格,编号,图案(集合)这些属性,其中编号是必须的,而别的是可选的,如果用户没有指定就是默认值。那么如果我们使用工厂模式,对应这四种可变参数,将会产生4 + 6 + 4 + 1 = 15种构造函数,这肯定不是我们想要的,因此我们采用Builder进行实现。

public class Product {
    private int pId,width,height,length;
    private List<Integer> patterns;
    private long cost;

    privateProduct(int pId, int width, int height, int length, List<Integer> patterns, long cost) {
        this.pId = pId;
        this.width = width;
        this.height = height;
        this.length = length;
        this.patterns = patterns;
        this.cost = cost;
    }

    static class ProductBuilder{
        private int pId,width,height,length;
        private List<Integer> patterns;
        private long cost;

        public ProductBuilder(int pId) {
            this.pId = pId;
            patterns = new LinkedList<>();
            //default value
            width = 500;
            height = 500;
            length = 500;
            cost = 1000;
        }
        public ProductBuilder setCost(long cost){
            this.cost = cost;
            return this;
        }
        public ProductBuilder setWidth(int width){
            this.width = width;
            return this;
        }
        public ProductBuilder setHeight(int height){
            this.height = height;
            return this;
        }

        public ProductBuilder setLength(int length){
            this.length = length;
            return this;
        }
        public ProductBuilder appendPattern(int patternId){
            this.patterns.add(patternId);
            return this;
        }
        public Product build(){
            return new Product(pId,width,height,length,patterns,cost);
        }
    }
}

可以从上面的实现看出,builder模式有效的减少了代码的数量,并且增加了灵活性和可读性。对于Product中的patterns这个List,使用Builder后用户甚至不需要自己初始化List,也不用关心Builder中的List是如何实现的,这一点使得Builder让内部逻辑对用户不可见。
在实现ProductBuilder时用到了几个小技巧,首先用private修饰Product的构造函数,使得用户只能通过Builder来构造Product,使得产品的发布更加安全。同时由于构造函数为private,因此Builder必须是Product的静态内部类。最后对于Builder中的每一个函数,都采用了函数式编程的思想,将返回值设为ProductBuilder本身,因为Builder的创建过程本身就是一套固定的流程,很少有需要判断(分支)的地方,因此用函数式可读性更高。(当然并不是所有的builder都是固定的流程,因此不是所有builder都适合函数式,这个取决于具体情况。)

例子

Builder模式很常见,列如JDK中的StringBuilder,各种框架的初始化,如Netty的ServerBootstrap,Spring的SpringApplicationBuilder。

优点

  • 解决复杂的产品生产流程,减少代码量,解决Java中多可配置参数导致的构造函数数量爆炸的问题
  • 用户能自由的选择产品的生产流程,然而产品生产的逻辑却对用户不可见。
  • 可读性强,写着爽
  • 延迟初始化,惰性.

缺点

  • 没什么缺点

相关文章

网友评论

      本文标题:设计模式学习笔记----建造者

      本文链接:https://www.haomeiwen.com/subject/xeuafctx.html