抽絲剝繭 細說架構那些事——【優銳課】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