深入探索Java设计模式之构建器模式(五)
抽丝剥茧 细说架构那些事——【优锐课】
简单的程序不需要大量的设计过程,因为它们只关注有限的解决方案,仅使用几个类。大型程序专注于广泛的设计,该设计比好的设计范例的任何其他属性都更能利用可重用性。宏伟的想法不仅是为当前问题提供解决方案,而且是创建一种设计,为将来的变化奠定基础。复杂的程序需要数千行代码以及对象和用户之间的大量交互。这些类型的解决方案通常在使用数千台柜员机操作的空中交通管制系统和银行系统中找到。本文是在学习完优锐课JAVA架构VIP课程—【框架源码专题】中《学习源码中的优秀设计模式》后写下的学习感悟。在这里,我们探索一种称为“构建器模式”的设计模式,并使用Java代码示例对其进行实现。
总览
有效的软件设计不仅可以满足当前的要求,而且可以构成未来更改和开发的基础。说起来比在实际应用中做起来容易。但是,设计模式无疑在很大程度上减轻了代码设计的负担。模式是用于构建灵活且可维护的软件的成熟架构。它通过一套标准的规范和实践大大降低了代码的复杂性。
有许多可用的设计模式,开发人员可以根据代码流的最佳表达选择一种。不选择不符合你需求的产品几乎是不可能的。实际上,设计模式是某人已经遇到问题并设计最佳实践以获得解决方案的证明。但是,它们绝不是天意。一个更好的主意可以随时替换它们。在和平环境下的叛乱是自杀的。尽管人们可以摆脱困境并做自己的事,但在大多数情况下遵循某种设计模式是有帮助的。
构建器模式
设计模式根据其特征命名。例如,构建器模式列出了构建类结构的规范。在实例化面向对象编程中的类时特别有用。想法是将复杂对象的构造与其表示分离。它利用灵活性来设计Java之类的对象。当我们开始编码时,很容易感觉到这种设计模式的便利性。
使用构建器模式
此模式对于创建具有许多字段或属性的类的实例特别有用。显而易见的是,在这种情况下,构造函数非常麻烦。例如,在这样的类中:
- public class Person {
- private final long id;
- private final String firstName;
- private final String middleName; //optional
- private final String lastName; //optional
- private final Date birthDate;
- private final String phone;
- private final String email;
- private final String street; //optional
- private final String city; //optional
- private final String province;
- private final String zip;
- // ...
要创建此类的实例,我们可以:
- 使用单个构造函数用值初始化字段
- 使用多个构造函数
- 使用无参数构造函数实例化对象后,使用setter方法
尽管这些都是语法上有效的技术,但它们在实践中非常麻烦。随着字段数量的增加,很快将变得难以管理和理解。使用单个构造函数是一个坏主意,首先是因为用庞大的参数化构造函数初始化许多字段是一个不好的设计。其次,有一些选择可以消除可选字段。使用多个构造函数不是一个好主意,因为如果将来增加字段的数量,它将很快变得难以管理。
第三种方法是根本不使用任何构造函数,而是从字段中删除final修饰符并使用setter方法进行初始化。该技术的问题在于,我们可以使用setter方法创建此类的无效对象。例如,以下内容尽管在语法上有效,但却是该类在语义上无效的实例。
- Person person = new Person();
- person.setCity("Mumbai");
请注意,人员对象的定义不仅是城市字段的有效初始化,而且至少是非可选字段的正确初始化。这是setter方法初始化的真正问题。
实现构建器模式
我们可以使用构建器模式来克服上面讨论的所有问题。在这里,通过这种技术,我们创建了一个称为生成器的伴随对象。此配套对象用于构造合法域对象。这不仅提高了代码的清晰度,而且使构造变得简单。
- public class Person {
- public static class Builder {
- private long id;
- private String firstName;
- private String middleName; //optional
- private String lastName; //optional
- private Date birthDate;
- private String phone;
- private String email;
- private String street; //optional
- private String city; //optional
- private String province;
- private String zip;
- public Builder id(final long id) {
- this.id = id;
- return this;
- }
- public Builder firstName(final String firstName) {
- this.firstName = firstName;
- return this;
- }
- public Builder middleName(final String middleName) {
- this.middleName = middleName;
- return this;
- }
- public Builder lastName(final String lastName) {
- this.lastName = lastName;
- return this;
- }
- public Builder birthDate(final Date birthDate) {
- this.birthDate = birthDate;
- return this;
- }
- public Builder phone(final String phone) {
- this.phone = phone;
- return this;
- }
- public Builder email(final String email) {
- this.email = email;
- return this;
- }
- public Builder street(final String street) {
- this.street = street;
- return this;
- }
- public Builder city(final String city) {
- this.city = city;
- return this;
- }
- public Builder province(final String province) {
- this.province = province;
- return this;
- }
- public Builder zip(final String zip) {
- this.zip = zip;
- return this;
- }
- public Person build(){
- if(id <= 0 || firstName.isEmpty() ||
- birthDate == null || phone.isEmpty() ||
- email.isEmpty() || province.isEmpty() ||
- zip.isEmpty()){
- throw new IllegalStateException("Cannot create
- Person object.");
- }
- return new Person(id,firstName,middleName,lastName,
- birthDate,phone,email,street,city,province,zip);
- }
- }
- private final long id;
- private final String firstName;
- private final String middleName; //optional
- private final String lastName; //optional
- private final Date birthDate;
- private final String phone;
- private final String email;
- private final String street; //optional
- private final String city; //optional
- private final String province;
- private final String zip;
- private Person(final long id, final String firstName,
- final String middleName, final String lastName,
- final Date birthDate, final String phone,
- final String email, final String street,
- final String city, final String province,
- final String zip) {
- this.id = id;
- this.firstName = firstName;
- this.middleName = middleName;
- this.lastName = lastName;
- this.birthDate = birthDate;
- this.phone = phone;
- this.email = email;
- this.street = street;
- this.city = city;
- this.province = province;
- this.zip = zip;
- }
- }
Builder类是Person类的一部分,用于构造Person对象。对于构造函数,参数以特定方式排序。结果,它们以相同顺序传递。使用构建器模式时,顺序无关紧要,并且可以在构造过程中以任何顺序传递值。请注意,在这种情况下,构造函数被设为私有。
- @Test
- public void rightBuild() {
- final Person.Builder builder = new Person.Builder();
- final Person emp = builder
- .id(101)
- .firstName("Percy")
- .middleName("Bysshe")
- .lastName("Shelley")
- .birthDate(new GregorianCalendar(1792,
- Calendar.AUGUST,4).getTime())
- .phone("1234567890")
- .email("pbs@gmail.com")
- .street("123 somewhere")
- .province("someplace")
- .zip("10293847").build();
- }
- @Test(expected = IllegalStateException.class)
- public void wrongBuild() {
- final Person.Builder builder = new Person.Builder();
- final Person emp = builder
- .middleName("Bysshe")
- .lastName("Shelley")
- .phone("1234567890")
- .zip("10293847").build();
- }
在测试方法中观察我们如何通过调用builder方法和一系列方法调用来创建对象。最后,调用build()方法以结束链并完成对象的创建。这就是我们用Java代码实现构建器模式的方式。
结论
本质是了解构建器模式背后的原理并以自己的方式实现。但是,在所有情况下,模式几乎都保持不变。如指定的那样,在必须初始化类中的大量字段的情况下,构建器模式特别有用。每个类都不适合使用此模式。可以看出,为方便起见,代码行增加了。明智地谨慎使用它。
感谢阅读!欢迎留言。想更深入探讨学习也欢迎私信我。
深入探索Java设计模式之构建器模式(五)的更多相关文章
- Java设计模式系列-装饰器模式
原创文章,转载请标注出处:<Java设计模式系列-装饰器模式> 一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是 ...
- java设计模式之七装饰器模式(Decorator)
顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下: Source类是被装饰类,Decorator类是一个 ...
- java设计模式之 装饰器模式
装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构. 这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装 ...
- Java设计模式之装饰器模式
1.装饰器模式的定义(保持接口,扩展功能) Decorate装饰器,顾名思义,就是动态的给一个对象添加一些额外的职责,就好比对房子进行装修一样. 2.装饰器模式的特征 具有一个装饰对象. 必须拥有与被 ...
- java设计模式之装饰器模式以及在java中作用
在JAVA I/O类库里有很多不同的功能组合情况,这些不同的功能组合都是使用装饰器模式实现的,下面以FilterInputStream为例介绍装饰器模式的使用 FilterInputStream和F ...
- java 设计模式 之 装饰器模式
装饰器模式的作用 在不修改原先对象核心的功能的情况下,对功能进行增强. 增强对象的功能的途径 通过类继承的方式,对父对象进行增强操作,例如造车是父类,改装跑车,跑车加大灯,改装房车,房车加私人电影院. ...
- 深入探索Java设计模式(三)之装饰器模式
装饰器模式使你可以在运行时使用类似于对象组成的技术来装饰类.这在我们希望实例化具有新职责的对象而无需对基础类进行任何代码更改的情况下尤其有用.本文是在学习完优锐课JAVA架构VIP课程—[框架源码专题 ...
- 深入探索Java设计模式(二)之策略模式
策略设计模式是Java API库中常见的模式之一.这与另一个设计模式(称为状态设计模式)非常相似.本文是在学习完优锐课JAVA架构VIP课程—[框架源码专题]中<学习源码中的优秀设计模式> ...
- 深入探索Java设计模式(四)之享元模式
享元模式适用于需要大量相同类型对象的情况.在此,设计布局可以减少创建多个对象的方式.对象在运行时会消耗资源,因此最好在内存中使用较少的对象.它减少了内存占用并利用了程序的整体性能.本文是在学习完优锐课 ...
随机推荐
- 2019-9-25:渗透测试,基础学习,Hydra BP爆破,js基本知识,banner信息收集笔记
使用BP和Hydra爆破相关的服务hydra:九头蛇,开源的功能强大的爆破工具,支持的服务有很多,使用hydra爆破c/s结构的服务,使用bp爆破web登陆窗口爆破需要的几个条件,爆破工具+字典字典: ...
- K8s 集群节点在线率达到 99.9% 以上,扩容效率提升 50%,我们做了这 3 个深度改造
点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 张振(守辰) ...
- (四十六)golang--网络编程(简易的聊天系统)
Go主要的目标之一就是面向大规模后端服务程序,网络通信这块是服务端程序必不可少也是至关键的一部分. 网络编程有两种: (1)TCP Socket编程:是网络编程的主流,之所以叫TCP Socket编程 ...
- es3设置属性不能修改
/*es3*/ { var Person =function () { var data ={ name:'zs', sex:'男', age:18 } this.get=function (key) ...
- Rust 入门 (四)
所有权是 rust 语言独有的特性,它保证了在没有垃圾回收机制下的内存安全,所以理解 rust 的所有权是很有必要的.接下来,我们来讨论所有权和它的几个特性:借用.切片和内存结构. 什么是所有权 Ru ...
- 品优购详情页---产品详细信息区域 iteminfo_wrap
产品详细信息区域为整个大盒子命名为: iteminfo_wrap 1号盒子命名为:sku_name 2号盒子命名为:news 3号盒子命名为:summary step1:3个盒子搭建框架,以及完成前两 ...
- 基于ManagedDataAccess开发的OracleDBHelpe工具集伸手党的福音
在使用前先加入ManagedDataAccessDLL文件方可使用 添加方法:右键项目.点击管理NuGet程序包,点击浏览,在输入框内输入ManagedDataAccess,再点击安装即可 Oracl ...
- jQuery上拉加载更多
<header id="header">首 页</header> <section id="main"> <ul id ...
- Scrapy爬虫及案例剖析
由于互联网的极速发展,所有现在的信息处于大量堆积的状态,我们既要向外界获取大量数据,又要在大量数据中过滤无用的数据.针对我们有益的数据需要我们进行指定抓取,从而出现了现在的爬虫技术,通过爬虫技术我们可 ...
- Spring Cloud Hoxton正式发布,Spring Boot 2.2 不再孤单
距离Spring Boot 2.2.0的发布已经有一个半月左右时间,由于与之匹配的Spring Cloud版本一直没有Release,所以在这期间碰到不少读者咨询的问题都是由于Spring Boot和 ...