iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java设计模式笔记之Builder模式
  • 304
分享到

Java设计模式笔记之Builder模式

2024-04-02 19:04:59 304人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录Builder模式是怎么来的关于Builder的一点说明线程安全问题经典的Builder模式总结当我第一次使用Picasso的时候,看见下面的官网示例时,我和我的小伙伴都惊呆了!

当我第一次使用Picasso的时候,看见下面的官网示例时,我和我的小伙伴都惊呆了!

Picasso.with(context).load("Http://i.imgur.com/DvpvklR.png").into(imageView);

如此简洁明了的使用方式,如此灵活多变的链式调用,让我深深地迷住了,然后我一直苦苦追求它,奈何天资愚笨,不知如何掀起它的神秘面纱...

不好意思,中二病又犯了,重来一遍。经过不懈的努力,终于发现它就是传说中的Builder(建造者)模式,并学会了如何与它亲密相处。

Builder模式是怎么来的

不知道是哪位贤人曾经说过,存在即为合理。Builder模式在众多的框架以及Android原生代码中存在(比如AlertDialog),就一定有其价值,用来解决某些需求。

考虑这样一个场景,假如有一个类(****User****),里面有很多属性,并且你希望这些类的属性都是不可变的(final),就像下面的代码:

public class User {
    private final String firstName;     // 必传参数
    private final String lastName;      // 必传参数
    private final int age;              // 可选参数
    private final String phone;         // 可选参数
    private final String address;       // 可选参数
}

在这个类中,有些参数是必要的,而有些参数是非必要的。就好比在注册用户时,用户的姓和名是必填的,而年龄、手机号和家庭地址等是非必需的。那么问题就来了,如何创建这个类的对象呢?

一种可行的方案就是实用构造方法。第一个构造方法只包含两个必需的参数,第二个构造方法中,增加一个可选参数,第三个构造方法中再增加一个可选参数,依次类推,直到构造方法中包含了所有的参数。

    public User(String firstName, String lastName) {
        this(firstName, lastName, 0);
    }

    public User(String firstName, String lastName, int age) {
        this(firstName, lastName, age, "");
    }

    public User(String firstName, String lastName, int age, String phone) {
        this(firstName, lastName, age, phone, "");
    }

    public User(String firstName, String lastName, int age, String phone, String address) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.phone = phone;
        this.address = address;
    }

这样做的好处只有一个:可以成功运行。但是弊端很明显:

  • 参数较少的时候问题还不大,一旦参数多了,代码可读性就很差,并且难以维护。
  • 对调用者来说也很麻烦。如果我只想多传一个address参数,还必需给age、phone设置默认值。而且调用者还会有这样的困惑:我怎么知道第四个String类型的参数该传address还是phone?

第二种解决办法就出现了,我们同样可以根据JavaBean的习惯,设置一个空参数的构造方法,然后为每一个属性设置setters和getters方法。就像下面一样:

public class User {
    private String firstName;     // 必传参数
    private String lastName;      // 必传参数
    private int age;              // 可选参数
    private String phone;         // 可选参数
    private String address;       // 可选参数

    public User() {
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }
}

这种方法看起来可读性不错,而且易于维护。作为调用者,创建一个空的对象,然后只需传入我感兴趣的参数。那么缺点呢?也有两点:

  • 对象会产生不一致的状态。当你想要传入5个参数的时候,你必需将所有的setXX方法调用完成之后才行。然而一部分的调用者看到了这个对象后,以为这个对象已经创建完毕,就直接食用了,其实User对象并没有创建完成。
  • ****User****类是可变的了,不可变类所有好处都不复存在。

终于轮到主角上场的时候了,利用Builder模式,我们可以解决上面的问题,代码如下:

public class User {
    private final String firstName;     // 必传参数
    private final String lastName;      // 必传参数
    private final int age;              // 可选参数
    private final String phone;         // 可选参数
    private final String address;       // 可选参数

    private User(UserBuilder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.age = builder.age;
        this.phone = builder.phone;
        this.address = builder.address;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }

    public static class UserBuilder {
        private final String firstName;
        private final String lastName;
        private int age;
        private String phone;
        private String address;

        public UserBuilder(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }

        public UserBuilder address(String address) {
            this.address = address;
            return this;
        }

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

有几个重要的地方需要强调一下:

  • ****User****类的构造方法是私有的。也就是说调用者不能直接创建User对象。
  • ****User****类的属性都是不可变的。所有的属性都添加了final修饰符,并且在构造方法中设置了值。并且,对外只提供getters方法。
  • Builder模式使用了链式调用。可读性更佳。
  • Builder的内部类构造方法中只接收必传的参数,并且该必传的参数适用了final修饰符。

相比于前面两种方法,Builder模式拥有其所有的优点,而没有上述方法中的缺点。客户端的代码更容易写,并且更重要的是,可读性非常好。唯一可能存在的问题就是会产生多余的Builder对象,消耗内存。然而大多数情况下我们的Builder内部类使用的是静态修饰的(static),所以这个问题也没多大关系。

现在,让我们看看如何创建一个User对象呢?

new User.UserBuilder("王", "小二")
                .age(20)
                .phone("123456789")
                .address("亚特兰蒂斯大陆")
                .build();

相当整洁,不是吗?你甚至可以用一行代码完成对象的创建。

关于Builder的一点说明

线程安全问题

由于Builder是非线程安全的,所以如果要在Builder内部类中检查一个参数的合法性,必需要在对象创建完成之后再检查。

public User build() {
  User user = new user(this);
  if (user.getAge() > 120) {
    throw new IllegalStateException(“Age out of range”); // 线程安全
  }
  return user;
}

上面的写法是正确的,而下面的代码是非线程安全的:

public User build() {
  if (age > 120) {
    throw new IllegalStateException(“Age out of range”); // 非线程安全
  }
  return new User(this);
}

经典的Builder模式

上面介绍的Builder模式当然不是“原生态”的啦,经典的Builder模式的类图如下:

builder

其中:

  • Product 产品抽象类。
  • Builder 抽象的Builder类。
  • ConcretBuilder 具体的Builder类。
  • Director 同一组装过程。

当然,之前实例中的Builder模式,是省略掉了Director的,这样结构更加简单。所以在很多框架源码中,涉及到Builder模式时,大多都不是经典GoF的Builder模式,而是省略后的。

总结

到此这篇关于Java设计模式笔记之Builder模式的文章就介绍到这了,更多相关Java设计模式Builder模式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java设计模式笔记之Builder模式

本文链接: https://www.lsjlt.com/news/141711.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java设计模式笔记之Builder模式
    目录Builder模式是怎么来的关于Builder的一点说明线程安全问题经典的Builder模式总结当我第一次使用Picasso的时候,看见下面的官网示例时,我和我的小伙伴都惊呆了!...
    99+
    2024-04-02
  • java设计模式笔记之代理模式
    代理(Proxy)模式:代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。核心作用:通过代理,控制对对象的访问。可以详细控制访问某个(某类)对象的方法,在调用这个方法之前做前置处理,在调用这个方...
    99+
    2023-05-31
    java 设计模式 代理模式
  • Java设计模式之单例模式
    目录什么是设计模式?单例模式是什么?单例模式设计的原则是什么?Java实现单例模式的5种方式?懒汉饿汉静态内部类双重校验锁DCL(Double Check Lock)枚举(num)总...
    99+
    2024-04-02
  • Java设计模式之策略模式
    在一个收银系统中,如果普通用户、中级会员、高级会员分别对应着不同的优惠策略,常规编程就要使用一系列的判断语句,判断用户类型,这种情况下就可以使用策略模式。 一、概念理解 策略模式的概...
    99+
    2022-11-13
    Java 设计模式 策略模式
  • Java设计模式之桥接模式
    本文通过老王和小王买车,引出设计模式中的结构型设计之桥接模式,接着说明设计型模式的概念和代码实现,为了加深理解,会说明适配器设计模式在JDBC中的应用,最后谈谈桥接模式和适配器模式的...
    99+
    2024-04-02
  • Java设计模式之外观模式
    本文通过老王改造小王公司的整体架构来说明外观模式,所谓的外观模式其实就是在各种复杂的子系统中抽象出来一个接口,隐藏具体的实现细节,调用方调用时只需要调用接口即可。为了加深理解我们会选...
    99+
    2024-04-02
  • Java设计模式之状态模式
    实际开发中订单往往都包含着订单状态,用户每进行一次操作都要切换对应的状态,而每次切换判断当前的状态是必须的,就不可避免的引入一系列判断语句,为了让代码更加清晰直观,我们引入今天的主角...
    99+
    2022-11-13
    Java 设计模式 状态模式
  • Java设计模式之享元模式
    本文通过优化买票的重复流程来说明享元模式,为了加深对该模式的理解,会以String和基本数据类型的包装类对该模式的设计进一步说明。 读者可以拉取完整代码到本地进行学习,实现代码均测试...
    99+
    2024-04-02
  • Java设计模式之命令模式
    本文通过解决老王经常搞错借书人的问题,来引出行为型模式中的命令模式。为了在案例之上理解的更加透彻,我们需要了解命令模式在源码中的应用。最后指出命令模式的应用场景和优缺点。 读者可以拉...
    99+
    2024-04-02
  • Java设计模式之代理模式
    本文由老王出租房子引出——代理设计模式,将从最简单的静态代理实现开始,后延伸使用jdk实现动态代理,最后扩展到Cglib实现动态代理。为了更深入理解代理模式,...
    99+
    2024-04-02
  • Java设计模式之组合模式
    本文通过老王和小王探讨书房、书架、各类书的管理问题,引出结构型设计模式家族中的一个重要成员——组合模式,本文会给予两种组合模式的典型代码实现,为了加深理解会在...
    99+
    2024-04-02
  • Java设计模式之模板方法模式
    在我们实际开发中,如果一个方法极其复杂时,如果我们将所有的逻辑写在一个方法中,那维护起来就很困难,要替换某些步骤时都要重新写,这样代码的扩展性就很差,当遇到这种情况就要考虑今天的主角...
    99+
    2022-11-13
    Java 设计模式 模板方法模式
  • Java设计模式之观察者模式(Observer模式)
    目录一、观察者模式是什么?二、模式分析2.1 四个角色2.2 案例三、观察者模式的优缺点四、总结一、观察者模式是什么? 当对象间存在一对多关系时,则使用观察者模式(Observer ...
    99+
    2024-04-02
  • Java设计模式之观察者模式
    目录一、观察者模式的定义和特点二、观察者模式的结构三、代码实例代码示例总结 一、观察者模式的定义和特点 观察者模式的定义: 指多个对象间存在一对多的依赖关系,当一个对象的状态发生改...
    99+
    2024-04-02
  • Java设计模式之装饰器模式
    本文由老王将建好的书房计划请小王来帮忙,小王却想谋权篡位,老王通过教育他引出装饰器设计模式,第二部分针对老王提出的建设性意见实现装饰器模式,第三部分针对装饰器模式在Jdk中的IO、S...
    99+
    2024-04-02
  • Java设计模式之解释器模式
    解释器模式字面意思,也即解释某些内容的含义。这种设计模式是实际开发中最不容易用到的。比如SQL解析,符号处理引擎,会用到解释器模式,属于更底层的开发人员才会用到的设计模式。 本文就以...
    99+
    2024-04-02
  • Java设计模式之中介者模式
    在我们实际业务中,可能存在多个类之间相互调用,形成了一个复杂的网状结构。这时候就需要有一种模式去“捋顺”他们之间的关系,引出一个中间者让类之间不再相互调用,该...
    99+
    2022-11-13
    Java 设计模式 中介者模式
  • Java设计模式之责任链模式
    本文通过图书馆管理系统中,用户名校验、密码校验、需要增加问题,每次都要增加if判断语句,将其改用责任链模式进行链式调用,为了让代码更加的优雅,我们使用之前学过的建造者模式就代码进行改...
    99+
    2024-04-02
  • Java设计模式之备忘录模式
    无论是我们在使用word还是记事本,系统都会为我们提供撤销的功能,这几乎是人人都会使用到的功能,而在我们实际开发中,会不会存在一个很复杂的对象,当更改了其中的某一个属性以后,也提供撤...
    99+
    2022-11-13
    Java 设计模式 备忘录模式
  • Java设计模式之建造者模式
    本文由老王家组装电脑引出——建造者设计模式,详细介绍建造者模式的基本概念和实现代码,为了便于理解建造者模式,我们会对实际应用中的典型案例进行介绍。最后对比工厂...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作