抽丝剥茧 细说架构那些事——【优锐课】html
简单的程序不须要大量的设计过程,由于它们只关注有限的解决方案,仅使用几个类。大型程序专一于普遍的设计,该设计比好的设计范例的任何其余属性都更能利用可重用性。宏伟的想法不只是为当前问题提供解决方案,并且是建立一种设计,为未来的变化奠基基础。复杂的程序须要数千行代码以及对象和用户之间的大量交互。这些类型的解决方案一般在使用数千台柜员机操做的空中交通管制系统和银行系统中找到。本文是在学习完优锐课JAVA架构VIP课程—【框架源码专题】中《学习源码中的优秀设计模式》后写下的学习感悟。在这里,咱们探索一种称为“构建器模式”的设计模式,并使用Java代码示例对其进行实现。编程
有效的软件设计不只能够知足当前的要求,并且能够构成将来更改和开发的基础。提及来比在实际应用中作起来容易。可是,设计模式无疑在很大程度上减轻了代码设计的负担。模式是用于构建灵活且可维护的软件的成熟架构。它经过一套标准的规范和实践大大下降了代码的复杂性。函数
有许多可用的设计模式,开发人员能够根据代码流的最佳表达选择一种。不选择不符合你需求的产品几乎是不可能的。实际上,设计模式是某人已经遇到问题并设计最佳实践以得到解决方案的证实。可是,它们毫不是天意。一个更好的主意能够随时替换它们。在和平环境下的叛乱是自杀的。尽管人们能够摆脱困境并作本身的事,但在大多数状况下遵循某种设计模式是有帮助的。学习
设计模式根据其特征命名。例如,构建器模式列出了构建类结构的规范。在实例化面向对象编程中的类时特别有用。想法是将复杂对象的构造与其表示分离。它利用灵活性来设计Java之类的对象。当咱们开始编码时,很容易感受到这种设计模式的便利性。测试
此模式对于建立具备许多字段或属性的类的实例特别有用。显而易见的是,在这种状况下,构造函数很是麻烦。例如,在这样的类中:ui
1 public class Person { 2 3 private final long id; 4 private final String firstName; 5 private final String middleName; //optional 6 private final String lastName; //optional 7 private final Date birthDate; 8 private final String phone; 9 private final String email; 10 11 private final String street; //optional 12 private final String city; //optional 13 private final String province; 14 private final String zip; 15 // ...
要建立此类的实例,咱们能够:
尽管这些都是语法上有效的技术,但它们在实践中很是麻烦。随着字段数量的增长,很快将变得难以管理和理解。使用单个构造函数是一个坏主意,首先是由于用庞大的参数化构造函数初始化许多字段是一个很差的设计。其次,有一些选择能够消除可选字段。使用多个构造函数不是一个好主意,由于若是未来增长字段的数量,它将很快变得难以管理。
第三种方法是根本不使用任何构造函数,而是从字段中删除final修饰符并使用setter方法进行初始化。该技术的问题在于,咱们可使用setter方法建立此类的无效对象。例如,如下内容尽管在语法上有效,但倒是该类在语义上无效的实例。
1 Person person = new Person(); 2 person.setCity("Mumbai");
请注意,人员对象的定义不只是城市字段的有效初始化,并且至少是非可选字段的正确初始化。这是setter方法初始化的真正问题。
咱们可使用构建器模式来克服上面讨论的全部问题。在这里,经过这种技术,咱们建立了一个称为生成器的伴随对象。此配套对象用于构造合法域对象。这不只提升了代码的清晰度,并且使构造变得简单。
1 public class Person { 2 public static class Builder { 3 private long id; 4 private String firstName; 5 private String middleName; //optional 6 private String lastName; //optional 7 private Date birthDate; 8 private String phone; 9 private String email; 10 private String street; //optional 11 private String city; //optional 12 private String province; 13 private String zip; 14 public Builder id(final long id) { 15 this.id = id; 16 return this; 17 } 18 public Builder firstName(final String firstName) { 19 this.firstName = firstName; 20 return this; 21 } 22 public Builder middleName(final String middleName) { 23 this.middleName = middleName; 24 return this; 25 } 26 public Builder lastName(final String lastName) { 27 this.lastName = lastName; 28 return this; 29 } 30 public Builder birthDate(final Date birthDate) { 31 this.birthDate = birthDate; 32 return this; 33 } 34 public Builder phone(final String phone) { 35 this.phone = phone; 36 return this; 37 } 38 public Builder email(final String email) { 39 this.email = email; 40 return this; 41 } 42 public Builder street(final String street) { 43 this.street = street; 44 return this; 45 } 46 public Builder city(final String city) { 47 this.city = city; 48 return this; 49 } 50 public Builder province(final String province) { 51 this.province = province; 52 return this; 53 } 54 public Builder zip(final String zip) { 55 this.zip = zip; 56 return this; 57 } 58 public Person build(){ 59 if(id <= 0 || firstName.isEmpty() || 60 birthDate == null || phone.isEmpty() || 61 email.isEmpty() || province.isEmpty() || 62 zip.isEmpty()){ 63 throw new IllegalStateException("Cannot create 64 Person object."); 65 } 66 return new Person(id,firstName,middleName,lastName, 67 birthDate,phone,email,street,city,province,zip); 68 } 69 } 70 private final long id; 71 private final String firstName; 72 private final String middleName; //optional 73 private final String lastName; //optional 74 private final Date birthDate; 75 private final String phone; 76 private final String email; 77 private final String street; //optional 78 private final String city; //optional 79 private final String province; 80 private final String zip; 81 private Person(final long id, final String firstName, 82 final String middleName, final String lastName, 83 final Date birthDate, final String phone, 84 final String email, final String street, 85 final String city, final String province, 86 final String zip) { 87 this.id = id; 88 this.firstName = firstName; 89 this.middleName = middleName; 90 this.lastName = lastName; 91 this.birthDate = birthDate; 92 this.phone = phone; 93 this.email = email; 94 this.street = street; 95 this.city = city; 96 this.province = province; 97 this.zip = zip; 98 } 99 }
Builder类是Person类的一部分,用于构造Person对象。对于构造函数,参数以特定方式排序。结果,它们以相同顺序传递。使用构建器模式时,顺序可有可无,而且能够在构造过程当中以任何顺序传递值。请注意,在这种状况下,构造函数被设为私有。
1 @Test 2 public void rightBuild() { 3 final Person.Builder builder = new Person.Builder(); 4 final Person emp = builder 5 .id(101) 6 .firstName("Percy") 7 .middleName("Bysshe") 8 .lastName("Shelley") 9 .birthDate(new GregorianCalendar(1792, 10 Calendar.AUGUST,4).getTime()) 11 .phone("1234567890") 12 .email("pbs@gmail.com") 13 .street("123 somewhere") 14 .province("someplace") 15 .zip("10293847").build(); 16 } 17 @Test(expected = IllegalStateException.class) 18 public void wrongBuild() { 19 final Person.Builder builder = new Person.Builder(); 20 final Person emp = builder 21 .middleName("Bysshe") 22 .lastName("Shelley") 23 .phone("1234567890") 24 .zip("10293847").build(); 25 }
在测试方法中观察咱们如何经过调用builder方法和一系列方法调用来建立对象。最后,调用build()方法以结束链并完成对象的建立。这就是咱们用Java代码实现构建器模式的方式。
本质是了解构建器模式背后的原理并以本身的方式实现。可是,在全部状况下,模式几乎都保持不变。如指定的那样,在必须初始化类中的大量字段的状况下,构建器模式特别有用。每一个类都不适合使用此模式。能够看出,为方便起见,代码行增长了。明智地谨慎使用它。
感谢阅读!欢迎留言。想更深刻探讨学习也欢迎私信我。
原文出处:https://www.cnblogs.com/youruike-/p/12076008.html