设计模式之建造者模式

image.png

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战java

欢迎来到今天的学习,今天咱们一块儿来唠唠建造者模式。多唠叨几句,前面我有提到本月将会对java的设计模式精讲,欢迎点击头像,关注个人专栏,我会持续更新,加油!算法

系列文章:编程

设计模式之单例模式设计模式

设计模式之工厂模式markdown

....系列持续更新框架

话很少话,进入正题ide

建造者模式

建造者模式是另一个高频使用的建立型设计模式——一般叫 Builder 模式,中文通常叫建造者模式或生成器模式。函数

今天咱们改变下策略,先开始不讲原理,先从例子下手,从解决问题案例当中去寻求答案。你认为的那种答案。oop

先看建造者模式主要带来什么或者解决什么问题:post

  • 直接使用构造函数或者使用 set 方法来建立对象方不方便?,有没有一种简单的方法建立对象

  • 存在的价值,为何须要建造者模式建立对象

下面经过代码具体深刻理解,咱们只讲干货,让你看完就能解决如今你代码中的实际问题!

场景及案例分享

对同一种场景咱们用建造者模式和不用建造者模式来进行代码对比:

很简单,咱们建立学生对象

/** * 学生实体 * 不用建造者模式 */
public class Students {
    private String name;    //姓名
    private int age;        //年龄
    private String grade;   //班级
    private String gender;  //性别
    public Student(String name, int age, String grade, String gender) {
        this.name = name;
        this.age = age;
        this.grade = grade;
        this.gender = gender;
    }
    public Student(String name, int age, String grade) {
        this.name = name;
        this.age = age;
        this.grade = grade;
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
   
}

 //上述代码写了三个不一样参数的构造函数
public static void main(String[] args) {
    Student student01 = new Student("张三",26,"13班","男");
    
    Student student02 = new Student("张三",26,"13班");
    
    ...
}
复制代码

上述有问题吗,没有问题。这代码能够吗,你以为呢?问题显而易见(确定还有不少小伙伴日常工做中都是这么搞的)。上面这段代码没有使用建造者模式,因此咱们须要使用传统的 getter、setter 方法,并指定不一样的入参来构造对象。若是参数过多,业务比较多,那须要建立太多构造方法。

而使用建造者模式后的类,功能却发生了彻底不同的变化,以下所示:

/** * 学生实体 * * 使用建造者模式建立对象 */
public class Students {
    //全部属性
    private String name;   
    private int age;       
    private String grade;  
    private String gender; 
    
    public Students() {
    }
    
    //内部builder new对象
    public static Students builder() {
        return new Students();
    }
    
    //将属性做为步骤
    public Students name(String name) {
        this.name = name;
        return this;
    }
    //将属性做为步骤
    public Students age(int age) {
        this.age = age;
        return this;
    }
    //将属性做为步骤
    public Students grade(String grade) {
        this.grade = grade;
        return this;
    }
    //将属性做为步骤
    public Students gender(String gender) {
        this.gender = gender;
        return this;
    }
    
    //执行建立操做(最后封口return)
    public Students build() {
        validateObject(this);
        return this;
    }
    private void validateObject(Students Students) {
        //能够作基础预校验,或自定义校验
    }
    @Override
    public String toString() {
        return "Students{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", grade='" + grade + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}



 //用建造者模式来建立对象
public static void main(String[] args) {
    
    //建立对象
    Students st = Students.builder()
            .name("张三")
            .age("26")
            .grade("13班")
            .gender("男")
            .build();
            
      //建立对象
    Students st01 = Students.builder()
            .name("张三")
            .age("26")
            .grade("13班")
            .build();       
            
     //一步步建造一个个属性 
}

复制代码

这,就是建造者模式来搞定对象。咱们能够发现构建出了彻底不一样的对象实例,而使用传统的 getter、setter 方法,则须要写不少不一样的构造函数来应对变化。

因此说,使用建造者模式能更方便地帮助咱们按需进行对象的实例化,避免写不少不一样参数的构造函数,同时还能解决同一类型参数只能写一个构造函数的弊端。

虽然上面案例的实现比较简单,可是也充分演示了如何使用建造者模式。在实际的使用中,一般能够直接使用 lombok 的 @Builder 注解实现类自身的建造者模式

为何使用建造者模式来建立对象?存在的意义是什么

为何要使用建造者模式来建立类?在我看来,有如下几点缘由。

  • 第一,分步骤的属性赋值更适合屡次运算结果类建立场景。在面向对象软件开发中,不少时候建立类所须要的参数并非一次都能准备好的,好比,计算订单优惠价格、查询库存状态等,有的参数可能须要经过调用多个服务运算后才能得出,这时咱们能够根据已知参数预先对类进行建立,等有合适的参数时再设置类的属性,而不是等到全部结果都齐备后才去建立类。

  • 第二,不须要关心特定类型的建造者的具体算法实现。 好比,咱们在使用 StringBuilder 时,并不太关心它的具体代码实现,而是关心它提供给咱们的使用功能。这在某些须要快速复用的场景中,能起到提高编码效率的做用。

  • 第三,提升代码的可阅读性,简洁明了,须要哪一个功能(属性),就调用哪一个,方便阅读,可维护性强。内部属性扩展性极强,自由地组合对象属性

  • 第四知足开闭原则,这也是设计模式的优势。 每个建造者都相对独立,所以能方便地进行替换或新增,这就大大提高了代码的可扩展性。

固然,夸奖完,仍是要指出一些存在一些客观性存在的问题。

  • 使用范围有限。 建造者模式所建立的对象通常都须要有不少的共同点,若是对象实例之间的差别性很大,则不适合使用建造者模式。

  • 容易形成超类,业务繁多,新的建立步骤就会被加进来,这会形成代码量的急剧膨胀,类会变得臃肿,最终造成一个庞大的超大类。

Netty当中的建造者模式

咱们来看下Netty框架当中是怎么运用建造者模式的(Netty不懂的自行百度下,后续我会对Netty做出专题来说)。

你们还记得,在服务端启动的时候有个启动辅助类ServerBootStrap,咱们调用group方法、channel方法设置参数。这里面也使用了这种建造者链式编程来设置相关参数。

ServerBootstrap b = new ServerBootstrap();
//开始建立对象
b.group(bossGroup, workerGroup) //bossGroup和workerGroup 先不用管,本节主要讲建造者模式

            //赋值channel参数
            .channel(NioServerSocketChannel.class)
            //赋值option参数
            .option(ChannelOption.SO_BACKLOG, 100)
            //赋值handler参数
            .handler(new LoggingHandler(LogLevel.INFO))
            .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    System.out.println("服务启动");
                }
            });
    
复制代码

下面咱们来一块儿看下源码,源码我就直接从idea当中截图了,我会从中圈出重点:

先看group,设置完参数以后,便返回this对象

image.png

再看 childHandler,依然如此,是否是和咱们上面学生的例子是同样的

image.png

其余几个参数也是同样,你们能够自行看下。

总结

OK,今天咱们的建造者模式就讲到这里,感谢你的阅读,相信你能从中学到东西。同时也很是欢迎您的点赞,关注和分享!

我已经将本章收录在专题里,点击文章下方专题,关注专栏,我会天天发表干货,本月我会持续输入设计模式。咱们下期再见!

相关文章
相关标签/搜索