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

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

作者: 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