抽丝剥茧 细说架构那些事——【优锐课】

简单的程序不需要大量的设计过程,因为它们只关注有限的解决方案,仅使用几个类。大型程序专注于广泛的设计,该设计比好的设计范例的任何其他属性都更能利用可重用性。宏伟的想法不仅是为当前问题提供解决方案,而且是创建一种设计,为将来的变化奠定基础。复杂的程序需要数千行代码以及对象和用户之间的大量交互。这些类型的解决方案通常在使用数千台柜员机操作的空中交通管制系统和银行系统中找到。本文是在学习完优锐课JAVA架构VIP课程—【框架源码专题】中《学习源码中的优秀设计模式》后写下的学习感悟。在这里,我们探索一种称为“构建器模式”的设计模式,并使用Java代码示例对其进行实现。

深入探索Java设计模式(一)之单例模式

深入探索Java设计模式(二)之策略模式

深入探索Java设计模式(三)之装饰器模式

深入探索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代码实现构建器模式的方式。

结论

本质是了解构建器模式背后的原理并以自己的方式实现。但是,在所有情况下,模式几乎都保持不变。如指定的那样,在必须初始化类中的大量字段的情况下,构建器模式特别有用。每个类都不适合使用此模式。可以看出,为方便起见,代码行增加了。明智地谨慎使用它。

感谢阅读!欢迎留言。想更深入探讨学习也欢迎私信我。

最新文章

  1. 20145221 《信息安全系统设计基础》实验五 简单嵌入式WEB服务器实验
  2. .Net dll多个同名的程序集版本冲突共存与通过基本代码或探测定位程序集方案
  3. 【英语】Bingo口语笔记(73) - 以tly,tely结尾的误读
  4. android4.0访问不能网络解决方法
  5. 分页存储过程--From:桌面备份 -&gt; sql2005新功能.docx
  6. ExcelApplication 另存Excel的SaveAs函数
  7. android图标设计事宜
  8. 关于Qt信号与槽机制的传递方向性研究(结论其实是错误的,但是可以看看分析过程)
  9. 动画——animation部分
  10. 机器学习算法与实现 之 Logistic Regression---java实现
  11. 十二生肖&amp;天干地支
  12. JAVA 调用 R 语言之升华篇
  13. 例10-3 uva10375(唯一分解定理)
  14. .Net开发常用工具插件
  15. parquet列式文件实战(未完,待续)
  16. Windows批处理命令学习中遇到的坑--持续更新中
  17. web前端全栈学习之路
  18. GreenPlum数据库安装
  19. Android 浅谈 设计与屏幕适配 【1.6235449734285716】
  20. 安装Scipy出错的解决方法

热门文章

  1. goland_beego框架学习--api实现
  2. 【Luogu P1972】HH的项链
  3. C语言I博客作业11
  4. 【Android - 控件】之V - DrawerLayout的使用
  5. warning: rpmts_HdrFromFdno: Header V4 DSA/SHA1 Signature, key ID XXXXXX: NOKEY
  6. python脚本-简单读取有效python代码量
  7. Oracle SQL command slash
  8. tabBarItem是模型,只有控件才有textColor属性
  9. Python-车牌识别
  10. WebMagic 实现爬虫入门教程