版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、加微信:642945106 發(fā)送“贈送”領取贈送精品課程發(fā)數(shù)字“2”獲取眾籌列表下載APP76 | 開源實戰(zhàn)一(上):通過剖析Java JDK源碼學習靈活應用設計模式2020-04-27 王爭設計模式之美進入課程講述:馮永吉時長 10:57 大小 10.03M從今天開始,我們就正式地進入到實戰(zhàn)環(huán)節(jié)。實戰(zhàn)環(huán)節(jié)包括兩部分,一部分是開源項目實戰(zhàn),另一部分是項目實戰(zhàn)。在開源項目實戰(zhàn)部分,我會帶你剖析幾個經典的開源項目中用到的設計原則、思想和模式,這其中就包括對 Java JDK、Unix、Google Guava、Spring、MyBatis 這樣五個開源項目的分析。在項目實戰(zhàn)部分,我們精心挑選了幾個
2、實戰(zhàn)項目,手把手地帶你利用之前學過的設計原則、思想、模式,來對它們進行分析、設計和代碼實現(xiàn),這其中就包括鑒權限流、冪等重試、灰度發(fā)布這樣三個項目。接下來的兩節(jié)課,我們重點剖析 Java JDK 中用到的幾種常見的設計模式。學習的目的是讓你體會,在真實的項目開發(fā)中,要學會活學活用,切不可過于死板,生搬硬套設計模式的設計 與實現(xiàn)。除此之外,針對每個模式,我們不可能像前面學習理論知識那樣,分析得細致入微, 很多都是點到為止。在已經具備之前理論知識的前提下,我想你可以跟著我的指引自己去研 究,有哪里不懂的話,也可以再回過頭去看下之前的理論講解。話不多說,讓我們正式開始今天的學習吧!工廠模式在 Cale
3、ndar 類中的應用在前面講到工廠模式的時候,大部分工廠類都是以 Factory 作為后綴來命名,并且工廠類主要負責創(chuàng)建對象這樣一件事情。但在實際的項目開發(fā)中,工廠類的設計更加靈活。那我們就來看下,工廠模式在 Java JDK 中的一個應用:java.util.Calendar。從命名上,我們無法看出它是一個工廠類。Calendar 類提供了大量跟日期相關的功能代碼,同時,又提供了一個 getInstance() 工廠方法,用來根據(jù)不同的 TimeZone 和 Locale 創(chuàng)建不同的 Calendar 子類對象。也就是說, 功能代碼和工廠方法代碼耦合在了一個類中。所以,即便我們去查看它的源碼
4、,如果不細心的話,也很難發(fā)現(xiàn)它用到了工廠模式。同時,因為它不單單是一個工廠類,所以,它并沒有以 Factory 作為后綴來命名。Calendar 類的相關代碼如下所示,大部分代碼都已經省略,我只給出了 getInstance() 工廠方法的代碼實現(xiàn)。從代碼中, 我們可以看出, get Instance() 方法可以根據(jù)不同TimeZone 和 Locale,創(chuàng)建不同的 Calendar 子類對象,比如 BuddhistCalendar、JapaneseImperialCalendar、GregorianCalendar,這些細節(jié)完全封裝在工廠方法中,使用者只需要傳遞當前的時區(qū)和地址,就能夠獲得
5、一個 Calendar 類對象來使用,而獲得的對象具體是哪個 Calendar 子類的對象,使用者在使用的時候并不關心。123456789復制代碼public abstract class Calendar implements Serializable, Cloneable, Comparable/.public static Calendar getInstance(TimeZone zone, Locale aLocale) return createCalendar(zone, aLocale);private static Calendar createCalendar(TimeZo
6、ne zone,Locale aLocale) CalendarProvider provider = LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();10if (provider != null)11 try 12return provider.getInstance(zone, aLocale);13 catch (IllegalArgumentException iae) 14/ fall back to the default instantiation151
7、61718Calendar cal = null;19if (aLocale.hasExtensions() 20String caltype = aLocale.getUnicodeLocaleType(ca);21if (caltype != null) 22switch (caltype)23 case24buddhist:25cal = new BuddhistCalendar(zone, aLocale);26break;27case japanese:28cal = new JapaneseImperialCalendar(zone, aLocale);29break;30case
8、 gregory:31cal = new GregorianCalendar(zone, aLocale);32break;33343536if (cal = null) 37if (aLocale.getLanguage() = th & aLocale.getCountry()= TH)38 cal = new BuddhistCalendar(zone, aLocale);39 else if (aLocale.getVariant() = JP & aLocale.getLanguage() = ja40cal = new JapaneseImperialCalendar(zone,
9、aLocale);41 else 42cal = new GregorianCalendar(zone, aLocale);434445return cal;46/.47建造者模式在 Calendar 類中的應用還是剛剛的 Calendar 類,它不僅僅用到了工廠模式,還用到了建造者模式。我們知道,建造者模式有兩種實現(xiàn)方法,一種是單獨定義一個 Builder 類,另一種是將 Builder 實現(xiàn)為原始類的內部類。Calendar 就采用了第二種實現(xiàn)思路。我們先來看代碼再講解,相關代碼我貼在了下面。復制代碼1 public abstract class Calendar implements S
10、erializable, Cloneable, Comparable fieldsYEAR81 if (weekDate & !cal.isWeekDateSupported() 82 throw new IllegalArgumentException(week date is unsupported by +8384 for (int stamp = MINIMUM_USER_STAMP; stamp nextStamp; stamp+) 85 for (int index = 0; index = maxFieldIndex; index+) 86 if (fieldsindex = s
11、tamp) 87 cal.set(index, fieldsNFIELDS + index);88 break;8990919293 if (weekDate) 94 int weekOfYear = isSet(WEEK_OF_YEAR) ? fieldsNFIELDS + WEEK_OF_YEAR95 int dayOfWeek = isSet(DAY_OF_WEEK) ? fieldsNFIELDS + DAY_OF_WEEK :96 cal.setWeekDate(fieldsNFIELDS + WEEK_YEAR, weekOfYear, dayOfWeek);9798
12、plete();99100return cal;101102103 看了上面的代碼,我有一個問題請你思考一下:既然已經有了 getInstance() 工廠方法來創(chuàng)建 Calendar 類對象,為什么還要用 Builder 來創(chuàng)建 Calendar 類對象呢?這兩者之間的區(qū)別在哪里呢?實際上,在前面講到這兩種模式的時候,我們對它們之間的區(qū)別做了詳細的對比,現(xiàn)在,我們再來一塊回顧一下。工廠模式是用來創(chuàng)建不同但是相關類型的對象(繼承同一父類或者接口的一組子類),由給定的參數(shù)來決定創(chuàng)建哪種類型的對象。建造者模式用來創(chuàng)建一種類型的復雜對象,通過設置不同的可選參數(shù),“定制化”地創(chuàng)建不同的對象。網(wǎng)上有一個
13、經典的例子很好地解釋了兩者的區(qū)別。顧客走進一家餐館點餐,我們利用工廠模式,根據(jù)用戶不同的選擇,來制作不同的食物,比如披薩、漢堡、沙拉。對于披薩來說,用戶又有各種配料可以定制,比如奶酪、 西紅柿、起司,我們通過建造者模式根據(jù)用戶選擇的不同配料來制作不同的披薩。粗看 Calendar 的 Builder 類的 build() 方法,你可能會覺得它有點像工廠模式。你的感覺沒錯,前面一半代碼確實跟 getInstance() 工廠方法類似,根據(jù)不同的 type 創(chuàng)建了不同的Calendar 子類。實際上,后面一半代碼才屬于標準的建造者模式,根據(jù) setXXX() 方法設置的參數(shù),來定制化剛剛創(chuàng)建的 C
14、alendar 子類對象。你可能會說,這還能算是建造者模式嗎?我用第 46 講的一段話來回答你:我們也不要太學院派,非得把工廠模式、建造者模式分得那么清楚,我們需要知道的是,每個模式為什么這么設計,能解決什么問題。只有了解了這些最本質的東西,我們 才能不生搬硬套,才能靈活應用,甚至可以混用各種模式,創(chuàng)造出新的模式來解決特定 場景的問題。實際上,從 Calendar 這個例子,我們也能學到,不要過于死板地套用各種模式的原理和實現(xiàn),不要不敢做絲毫的改動。模式是死的,用的人是活的。在實際上的項目開發(fā)中,不僅各種模式可以混合在一起使用,而且具體的代碼實現(xiàn),也可以根據(jù)具體的功能需求做靈活的調整。裝飾器模
15、式在 Collections 類中的應用我們前面講到,Java IO 類庫是裝飾器模式的非常經典的應用。實際上,Java 的Collections 類也用到了裝飾器模式。Collections 類是一個集合容器的工具類,提供了很多靜態(tài)方法,用來創(chuàng)建各種集合容器, 比如通過 unmodifiableColletion() 靜態(tài)方法,來創(chuàng)建 UnmodifiableCollection 類對象。而這些容器類中的 UnmodifiableCollection 類、CheckedCollection 和SynchronizedCollection 類,就是針對 Collection 類的裝飾器類。復制
16、代碼1234567891011121314151617public class Collections private Collections() public static Collection unmodifiableCollection(Collection? extends return new UnmodifiableCollection(c);static class UnmodifiableCollection implements Collection,Serializaprivate static final long serialVersionUID = 182001775
17、2578914078L;final Collection c;UnmodifiableCollection(Collection c) if (c=null)throw new NullPointerException(); this.c = c;27282930private final Iterator i = c.iterator();public boolean hasNext() return i.hasNext();public E next()return i.next();因為剛剛提到的這三個裝飾器類,在代碼結構上幾乎一樣,所以,我們這里只拿其中的UnmodifiableCol
18、lection 類來舉例講解一下。UnmodifiableCollection 類是 Collections 類的一個內部類,相關代碼我摘抄到了下面,你可以先看下。18public int size()returnc.size();19public boolean isEmpty()returnc.isEmpty();20public boolean contains(Object o)returnc.contains(o);21public Object toArray()returnc.toArray();22public T toArray(T a)returnc.toArray(a);
19、23public String toString()returnc.toString();2425public Iterator iterator() 26return new Iterator() 31public void remove() 32throw new UnsupportedOperationException();3334Override35public void forEachRemaining(Consumer action)36/ Use backing collection version37i.forEachRemaining(action);3839;404142
20、public boolean add(E e) 43throw new UnsupportedOperationException();4445public boolean remove(Object o) 46hrow new UnsupportedOperationException();4748public boolean containsAll(Collection coll) 49return c.containsAll(coll);5051public boolean addAll(Collection coll) 52throw new UnsupportedOperationE
21、xception();5354public boolean removeAll(Collection coll) 55throw new UnsupportedOperationException();5657public boolean retainAll(Collection coll) 58throw new UnsupportedOperationException();5960public void clear() 61throw new UnsupportedOperationException();626364/ Override default methods in Colle
22、ction65Override66public void forEach(Consumer action) 67c.forEach(action);6869Override70public boolean removeIf(Predicate filter) 71throw new UnsupportedOperationException();7273SuppressWarnings(unchecked)74Override75public Spliterator spliterator() 76return (Spliterator)c.spliterator();7778Suppress
23、Warnings(unchecked)79Override80public Stream stream() 81return (Stream)c.stream();8283SuppressWarnings(unchecked)84Override85public Stream parallelStream() 86return (Stream)c.parallelStream();878889 看了上面的代碼,請你思考一下,為什么說 UnmodifiableCollection 類是 Collection 類的裝飾器類呢?這兩者之間可以看作簡單的接口實現(xiàn)關系或者類繼承關系嗎?我們前面講過,裝飾
24、器模式中的裝飾器類是對原始類功能的增強。盡管UnmodifiableCollection 類可以算是對 Collection 類的一種功能增強,但這點還不具備足夠的說服力來斷定 UnmodifiableCollection 就是 Collection 類的裝飾器類。實際上,最關鍵的一點是,UnmodifiableCollection 的構造函數(shù)接收一個 Collection 類對象,然后對其所有的函數(shù)進行了包裹(Wrap):重新實現(xiàn)(比如 add() 函數(shù))或者簡單封裝(比如 stream() 函數(shù))。而簡單的接口實現(xiàn)或者繼承,并不會如此來實現(xiàn)UnmodifiableCollection類。所
25、以,從代碼實現(xiàn)的角度來說,UnmodifiableCollection 類是典型的裝飾器類。適配器模式在 Collections 類中的應用在第 51 講中我們講到,適配器模式可以用來兼容老的版本接口。當時我們舉了一個 JDK的例子,這里我們再重新仔細看一下。老版本的 JDK 提供了 Enumeration 類來遍歷容器。新版本的 JDK 用 Iterator 類替代Enumeration 類來遍歷容器。為了兼容老的客戶端代碼(使用老版本 JDK 的代碼),我們保留了 Enumeration 類,并且在 Collections 類中,仍然保留了 enumaration() 靜態(tài)方法(因為我們一
26、般都是通過這個靜態(tài)函數(shù)來創(chuàng)建一個容器的 Enumeration 類對象)。不過,保留 Enumeration 類和 enumeration() 函數(shù),都只是為了兼容,實際上,跟適配器沒有一點關系。那到底哪一部分才是適配器呢?在新版本的 JDK 中,Enumeration 類是適配器類。它適配的是客戶端代碼(使用Enumeration 類)和新版本 JDK 中新的迭代器 Iterator 類。不過,從代碼實現(xiàn)的角度來說,這個適配器模式的代碼實現(xiàn),跟經典的適配器模式的代碼實現(xiàn),差別稍微有點大。enumeration() 靜 態(tài) 函 數(shù) 的 邏 輯 和 Enumeration 適 配 器 類 的 代
27、 碼 耦 合 在 一 起 , enumeration() 靜態(tài)函數(shù)直接通過 new 的方式創(chuàng)建了類對象。具體的代碼如下所示:1/*復制代碼2* Returns an enumeration over the specified collection.This provides3* interoperability with legacy APIs that require an enumeration4* as input.5*6* param the class of the objects in the collection7* param c the collection for whi
28、ch an enumeration is to be returned.8* return an enumeration over the specified collection.9* see Enumeration10*/11public static Enumeration enumeration(final Collection c) 12return new Enumeration() 13private final Iterator i = c.iterator();1415public boolean hasMoreElements() 16return i.hasNext();
29、171819public TnextElement() 20returni.next();212223 ;重點回顧好了,今天的內容到此就講完了。我們一塊來總結回顧一下,你需要重點掌握的內容。今天,我重點講了工廠模式、建造者模式、裝飾器模式、適配器模式,這四種模式在 Java JDK 中的應用,主要目的是給你展示真實項目中是如何靈活應用設計模式的。從今天的講解中,我們可以學習到,盡管在之前的理論講解中,我們都有講到每個模式的經典代碼實現(xiàn),但是,在真實的項目開發(fā)中,這些模式的應用更加靈活,代碼實現(xiàn)更加自由, 可以根據(jù)具體的業(yè)務場景、功能需求,對代碼實現(xiàn)做很大的調整,甚至還可能會對模式本身的設計思路
30、做調整。比如,Java JDK 中的 Calendar 類,就耦合了業(yè)務功能代碼、工廠方法、建造者類三種類型的代碼,而且,在建造者類的 build 方法中,前半部分是工廠方法的代碼實現(xiàn),后半部分才是真正的建造者模式的代碼實現(xiàn)。這也告訴我們,在項目中應用設計模式,切不可生搬硬套, 過于學院派,要學會結合實際情況做靈活調整,做到心中無劍勝有劍。課堂討論在 Java 中,經常用到的 StringBuilder 類是否是建造者模式的應用呢?你可以試著像我一樣從源碼的角度去剖析一下。歡迎留言和我分享你的想法。如果有收獲,也歡迎你把這篇文章分享給你的朋友。 版權歸極客邦科技所有,未經許可不得傳播售賣。 頁
31、面已增加防盜追蹤,如有侵權極客邦將依法追究其法律責任。上一篇75 | 在實際的項目開發(fā)中,如何避免過度設計?又如何避免設計不足?下一篇77 | 開源實戰(zhàn)一(下):通過剖析Java JDK源碼學習靈活應用設計模式精選留言 (10)寫留言Darren2020-04-27我覺得是,因為StringBuilder的主要方法append,其實就是類似于建造者模式中的set方法,只不過構建者模式的set方法可能是對象的不同屬性,但append其實是在一直修改一個屬性,且最后沒有build(),但StringBuilder出現(xiàn)的目的其實是為了解決String不可變的問題,最終輸出其實是String,所以可以類比toString()就是build(),所以認為算是建造者模式。展開4QQ怪2020-04-27StringBuilder的append()方法使用了建造者模式,StringBuilder把構建者的角色交給了其的父類AbstractStringBuilder,最終調用的是父類的append()方法展開2小晏子2020-04-27課后思考:我的答案是算也不算,如果按照學院派的思想,stringbuilder和GOF中的對于
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年山西省廣播電視局中波臺管理中心招聘應急廣播平臺值班員備考題庫及完整答案詳解1套
- 2026年吉水縣城控人力資源服務有限公司面向社會公開招聘勞務派遣人員至吉水縣審計局的備考題庫完整參考答案詳解
- 2026年勞務派遣人員招聘(派遣至浙江大學教育學院)備考題庫完整答案詳解
- Unit 7 Role models of our time第3課時Grammar公開課一等獎創(chuàng)新教學設計
- 人教版英語八年級下Unit 4Why don't you talk to your parents- 話題作文公開課一等獎創(chuàng)新教案及范文
- 2026年德陽市住房公積金管理中心羅江管理部編外聘用人員招聘備考題庫及答案詳解1套
- 2026年北京協(xié)和醫(yī)院內分泌科于淼課題組合同制科研助理招聘備考題庫附答案詳解
- 2026年全面參考農家樂加盟合同內容
- 2026年電動車銷售合同簡易版
- 2026年養(yǎng)殖場場地租賃合同
- 2025版中國胃癌保功能手術外科專家共識課件
- TGXAS-火龍果品質評價技術規(guī)范編制說明
- (2025)70周歲以上老年人換長久駕照三力測試題庫(含答案)3
- 口腔科門診主任年度工作匯報
- 福建省能源石化集團有限責任公司2025年秋季招聘備考題庫及一套完整答案詳解
- 2025年新聞記者資格證及新聞寫作相關知識題庫附答案
- DB32∕T 5188-2025 經成人中心靜脈通路裝置采血技術規(guī)范
- 深圳市2024-2025學年九年級上學期期末考試化學試卷(含答案)
- 白車身輕量化設計技術
- 華師 八年級 數(shù)學 下冊《17.2 平行四邊形的判定 》課件
- GB/T 17941-2008數(shù)字測繪成果質量要求
評論
0/150
提交評論