14談?wù)勀阒赖脑O(shè)計模式_第1頁
14談?wù)勀阒赖脑O(shè)計模式_第2頁
14談?wù)勀阒赖脑O(shè)計模式_第3頁
14談?wù)勀阒赖脑O(shè)計模式_第4頁
14談?wù)勀阒赖脑O(shè)計模式_第5頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、極客時間第14講 | 談?wù)勀阒赖脑O(shè)計模式?2018-06-05第14講 | 談?wù)勀阒赖脑O(shè)計模式?- 00:00 / 08:23設(shè)計模式是人們?yōu)?開發(fā)中相同表征的問題,抽象出的可重復(fù)利用的解決方案。在某種程度上,設(shè)計模式已經(jīng)代表了一些特定情況的最佳實踐,同時也起到了 工程師之間的“行話”的作用。理解和掌握典型的設(shè)計模式,有利于我們提高設(shè)計的效率和質(zhì)量。我要問你的問題是,談?wù)勀阒赖脑O(shè)計模式?請手動實現(xiàn)單例模式,Spring等框架中使用了哪些模式?典型回答大致按照模式的應(yīng)用目標(biāo) ,設(shè)計模式可以分為創(chuàng)建型模式 結(jié)構(gòu)型模為型模式。創(chuàng)建型模式,是對對象創(chuàng)建過程的各種問題和解決方案的總結(jié), 各種工廠模

2、式(Factory Abstract Factory) 單例模式(Singleton) 構(gòu)建器模式(Builder) 原型模式(ProtoType )。結(jié)構(gòu)型模式,是(Decorator)設(shè)計結(jié)構(gòu)的總結(jié),關(guān)注于類 對象繼承 組合方式的實踐經(jīng)驗。常見的結(jié)構(gòu)型模式, 橋接模式(Bridge) 適配器模式(Adapter) 裝飾者模式模式(Proxy) 組合模式(Composite) 外觀模式(Facade)模式(Flyweight)等。行為型模式,是從類或?qū)ο笾g交互 職責(zé)劃分等角度總結(jié)的模式。比較常見的行為型模式有策略模式(Strategy) 解釋器模式(Interpreter) 命令模式(d)

3、觀察者模式(Observer) 迭代器模式(Iterator) 模板 模式(Template Method )考點分析這個問題主要是考察你對設(shè)計模式的了解和掌握程度, 相關(guān)內(nèi)容你可以參考:者模式(Visitor)。 Patterns。我建議可以在回答時適當(dāng)?shù)嘏e些例子,更加清晰地說明典型模式到底是什么樣子,典型使用場景是怎樣的。這里舉個Java基礎(chǔ)類庫中的例子供你參考。首先,專欄第11講剛過IO框架,我們知道InputStream是一個抽象類,標(biāo)準(zhǔn)類庫中提供了FileInputStream ByteArrayInputStream等各種不同的子類,分別從不同角度對InputStream進行了功能

4、擴展,這是典型的裝飾器模式應(yīng)用案例。識別裝飾器模式,可以通過識別類設(shè)計特征來進行 ,也就是其類構(gòu)造函數(shù)以相同的抽象類或者接口為輸入?yún)?shù)。因為裝飾器模式本質(zhì)上是包裝同類型實例,我們對目標(biāo)對象的調(diào)用,往往會通過包裝類覆蓋過的 ,迂回調(diào)用被包裝的實例,這就可以很自然地實現(xiàn)增加額外邏輯的目的,也就是所謂的“裝飾”。例如,BuferedInputStream經(jīng)過包裝,為輸入流過程增加緩存,類似這種裝飾器還可以多次嵌套,不斷地增加不同層次的功能。我在下面的類 ,簡單總結(jié)了InputStream的裝飾模式實踐。public BuferedInputStream(InputStream in)極客時間接下來再

5、看第二個例子。創(chuàng)建型模式尤其是工廠模式,在我們的代碼中隨處可見,我舉個相對不同的API設(shè)計實踐。比如,JDK最新版本中 HTTP/2API,下面這個創(chuàng)建HttpRequest的過程,就是典型的構(gòu)建器模式(Builder),通常會被實現(xiàn)成fuent風(fēng)格的API,也有人叫它鏈。使用構(gòu)建器模式,可以比較優(yōu)雅地解決構(gòu)建復(fù)雜對象的麻煩,這里的“復(fù)雜”是指類似需要輸入的參數(shù)組合較多,如果用構(gòu)造函數(shù),我們往往需要為每一種可能的輸入?yún)?shù)組合實現(xiàn)相應(yīng)的構(gòu)造函數(shù),一系列復(fù)雜的構(gòu)造函數(shù)會讓代碼閱讀性和可維護性變得很差。上面的分析也進一步反映了創(chuàng)建型模式的初衷,即,將對象創(chuàng)建過程單獨抽象出來,從結(jié)構(gòu)上把對象使用邏輯和

6、創(chuàng)建邏輯相互 ,隱藏對象實例的細節(jié),進而為使用者實現(xiàn)了更加規(guī)范 統(tǒng)一的邏輯。更進一步進行設(shè)計模式考察,面試官可能會:希望你寫一個典型的設(shè)計模式實現(xiàn)。這雖然看似簡單,但即使是最簡單的單例,也能夠綜合考察代碼基本功??疾斓湫偷脑O(shè)計模式使用,尤其是結(jié)合標(biāo)準(zhǔn)庫或者主流開源框架,考察你對業(yè)界良好實踐的掌握程度。在面試時如果恰好問到你不熟悉的模式,你可以稍微引導(dǎo)一下,比如 你在 中使用了什么 相對熟悉的模式,試圖解決什么問題,它們的優(yōu)點和缺點等。下面,我會 前面兩點,結(jié)合代碼實例進行分析。知識擴展我們來實現(xiàn)一個日常非常熟悉的單例設(shè)計模式??雌饋硭坪鹾芎唵危敲聪旅孢@個樣例符合基本需求嗎?是不是總感覺缺了點

7、什么?原來,Java會自動為沒有明確 構(gòu)造函數(shù)的類,定義一個public的無參數(shù)的構(gòu)造函數(shù),所以上面的例子并不能保證額外的對象不被創(chuàng)建出來,別人完全可以直接“new Singleton()”,那我們應(yīng)該怎么處理呢?不錯,可以為單例定義一個private的構(gòu)造函數(shù)(也有建議 為枚舉,這是有爭議的,我個人不建議選擇相對復(fù)雜的枚舉,畢竟日常開發(fā)不是學(xué)術(shù)研究)。這樣還有什么改進的余地嗎?專欄第10講ConcurrentHashMap時,提到過標(biāo)準(zhǔn)類庫中很多地方使用懶加載(lazy-load), 初始內(nèi)存開銷,單例同樣適用,下面是 后的改進版本。這個實現(xiàn)在單線程環(huán)境不 問題,但是如果處于并發(fā)場景,就需要

8、考慮線程安全,最熟悉的就莫過于“ 這里的volatile能夠提供可見性,以及保證getInstance返回的是初始化完全的對象。在同步之前進行null檢查,以盡量避免進入相對昂貴的同步塊?!保湟c在于:public class Singleton private satic Singleton insance; private Singleton() public satic Singleton getInsance() if (insance = null) insance = new Singleton();return insance;public class Singleton pr

9、ivate satic Singleton insance = new Singleton(); public satic Singleton getInsance() return insance;HttpReques reques = HttpReques.newBuilder(new URI(uri).header(header , valueAl ce).headers(headerBob, value1Bob, headerCarl, valueCarl, headerBob, value2Bob).GET().build();極客時間直接在class級別進行同步,保證線程安全的類

10、調(diào)用。在這段代碼中,爭論較多的是volatile修飾靜態(tài)變量,當(dāng)Singleton類本身有多個成員變量時,需要保證初始化過程完成后,才能被get到。在現(xiàn)代Java中,內(nèi)存排序模型(JMM)已經(jīng)非常完善,通過volatile的write或者,能保證所謂的happen-before,也就是避免常被提到的指令重排。換句話說,構(gòu)造對象的store指令能夠被定在volatile之前。當(dāng)然,也有一些人推薦利用內(nèi)部類持有靜態(tài)對象的方式實現(xiàn),其理論依據(jù)是對象初始化過程中隱含的初始化鎖(有 的話你可以參考jls-12.4 2 中對LC的說明),這種和前面的雙檢鎖實現(xiàn)都能保證線程安全,不過語法稍顯晦澀,未必有特別

11、的優(yōu)勢。所以,可以看出,即使是看似最簡單的單例模式,在增加各種高標(biāo)準(zhǔn)需求之后,同樣需要非常多的實現(xiàn)考量。上面是比較學(xué)究的考察,其實實踐中未必需要如此復(fù)雜,如果我們看Java 類庫 的單例實現(xiàn),比如java lang.Runtime,你會發(fā)現(xiàn):它并沒使用復(fù)雜的之類。靜態(tài)實例被為fnal,這是被通常實踐忽略的,一定程度保證了實例不被篡改(專欄第6講過,反射之類可以繞過私有 限制),也有有限的保證執(zhí)行順序的語義。前面說了不少代碼實踐,下面一起來簡要看看主流開源框架,如Spring等如何在API設(shè)計中使用設(shè)計模式。你至少要有個大體的印象,如:BeanFactory和ApplicationContext

12、應(yīng)用了工廠模式。在Bean的創(chuàng)建中,Spring也為不同scope定義的對象,提供了單例和原型等模式實現(xiàn)。我在專欄第6講的AOP領(lǐng)域則是使用了 模式 裝飾器模式 適配器模式等。各種器,是觀察者模式的典型應(yīng)用。類似Template 等則是應(yīng)用了模板模式。,我與你回顧了設(shè)計模式的 和主要類型,并從Java 類庫 開源框架等不同角度分析了其采用的模式,并結(jié)合單例的不同實現(xiàn),分析了如何實現(xiàn)符合線程安全等需求的單例,希望可以對你的工程實踐有所幫助。另外, 最后補充的是,設(shè)計模式也不是銀彈,要避免 或者過度設(shè)計。一課一練關(guān)于設(shè)計模式你做到心中有數(shù)了嗎?你可以思考下,在業(yè)務(wù)代碼中,經(jīng)常發(fā)現(xiàn)大量XXFacad

13、e,外觀模式是解決什么問題?適用于什么場景?請你在留言區(qū)寫寫你對這個問題的思考,我會選出經(jīng)過認真思考的留言,送給你一份學(xué)習(xí)鼓勵金,歡迎你與我一起討論。你的朋友是不是也在準(zhǔn)備面試呢?你可以“請朋友讀”,把 的題目 給好友,或許你能幫到他。private satic fnal Runtime currentRuntime = new Runtime(); private satic Version version;/ public satic Runtime getRuntime() return currentRuntime;/* Don't let anyone else ins at

14、e this class */ private Runtime() public class Singleton private Singleton()public satic Singleton getSingleton() return Holder.singleton;private satic class Holder private satic Singleton singleton = new S ngleton();public class Singleton private satic volatile Singleton singleton = null; private S

15、ingleton() public satic Singleton getSingleton() if (singleton = null) / 盡量避免重復(fù)進入同步塊synchronized (Singleton.class) / 同步.class 意味著對同步類 調(diào)用if (singleton = null) singleton = new Singleton();return singleton;極客時間sunlight0012018-06-05fascade是門面模式 為復(fù)雜的邏輯提供簡單的借口 設(shè)計模式學(xué)的時候還能明白 但是用的結(jié)合流行的開源框架 或者 的項目學(xué)設(shè)計模式是很 辦法 生

16、學(xué)很容易看不懂學(xué)不下去時候就不知道該怎么用了 我們怎么在項目中使用設(shè)計模式呢?作者回復(fù)2018-06-06不必為了模式而用 優(yōu)先解決開發(fā)、維護中的痛點公號-Java大后端2018-06-05之前放置了一個新的 對象 只能通過該對象才能使用該系統(tǒng) 不再 其它方式 該系統(tǒng) 該 對象封裝了 原系統(tǒng)的所有規(guī)則和接口提供門面模式形象上來講就是的API接口較之使用原系統(tǒng)會更加的簡單舉例:JUnitCore是JUnit類的 Facade模式的實現(xiàn)類 外部使用該 對象與JUnit進行統(tǒng)一交互 驅(qū)動執(zhí) 試代碼使用場景:當(dāng)我們希望封裝或隱當(dāng)我們使用原系統(tǒng)的功能并希望增加一些新的功能 編寫新類的成本遠小于所有人學(xué)會

17、使用或者未來維護原系統(tǒng)所需的成本缺點: 了開閉原則擴展 只能直接修改 對象作者回復(fù)2018-06-06不錯文TSOS2018-06-05為什么我去查Runtime的源碼 currentRuntime沒有被fnal修飾呢?作者回復(fù)2018-06-06什么版本?我這是最新的云學(xué)2018-06-09最開始迷戀設(shè)計模式 后來眼中沒有模式 其實 經(jīng)典的設(shè)計模式的書的第一章就非常明確的指出設(shè)計模式不是銀彈 總感覺java語言寫的c+更重 很多代碼都是無用的裝飾李志博2018-06-05Spring 內(nèi)部的asm 模塊 用到了 者模式Sin02018-06-05有一點理解不太一致 單例模式double ch

18、eck中synchronized就已經(jīng)可以提供可見性 volatile的作用主要體現(xiàn)在禁指令重排!作者回復(fù)2018-06-06不sync也不是必然走到潤茲2018-06-05在沒用facade之前 為了完成某個功能需要調(diào)用的各 進行組合才能完成 用了facade之后相當(dāng)于把多個 調(diào)用聚 了一個方便用戶調(diào)用2018-06-06公司項目是一個基于s boot、mybatis開發(fā)的web后端管理項目 現(xiàn)在的問題是 不同角色登錄到系統(tǒng)看到的模塊和模塊里面的數(shù)據(jù)是不一樣的 有時雖然看到的模塊一樣 但是由于角色不一樣 所以顯示的數(shù)據(jù)是不一樣 在這樣的情況下 會經(jīng)常在service層 里面 角色然后改變ma

19、pper的數(shù)據(jù)操作條件或調(diào)用mapper的不同由于在service層頻繁的 角色感覺很不雅 新增角色就要加哎 感覺可以用策略設(shè)計模式不知道怎么具體設(shè)計星空2018-06-05外觀模式為子系統(tǒng)中一組接口提供一個統(tǒng)一 的接口 降低了客戶端與子系統(tǒng)之間的耦合 簡化了系統(tǒng)復(fù)雜度 缺點是 了開閉原則 適用于為一系列復(fù)雜的子系統(tǒng)提供一個友好簡單的入口 將子系統(tǒng)與客戶端解偶 公司基礎(chǔ)paas平臺用到了外觀模式 具體是定義一個ServiceFacade 然后通過繼承眾多xxService,對外提供子xxService的服務(wù)作者回復(fù)2018-06-06業(yè)務(wù)開發(fā)很普遍2018-07-11極客時間我有個疑問 單例那

20、里可否不用volatile 初始化時Singleton temp=new Singleton();this.singleton=temp;這樣能保證初始化完成才賦值嗎?Miaozhe2018-06-08提供統(tǒng)一的服務(wù) 就是 外部系統(tǒng)對內(nèi)部服務(wù)的具體實現(xiàn) 以及各微服務(wù)的部署虛擬機和URL我理解Facada模式 微服務(wù)應(yīng)用場景 如 Nginx對系統(tǒng)子服務(wù)進行管理和IP反向再者 容器Docker技術(shù) 我認為這是Facada模式 通過鏡像把應(yīng)用相關(guān)的組件和配置都預(yù)置好 發(fā)布這個服務(wù)時 直接啟動容器 用戶不用關(guān)心里面的任何細節(jié)楊 看看 我分析的對嗎?Walter2018-06-07外觀模式(Facade

21、 Pattern)隱的復(fù)雜性 并向客戶端提供了一個客戶端可以 系統(tǒng)的接口 它向現(xiàn)有的系統(tǒng)添加一個接口 來隱的復(fù)雜性這種模式涉及到一個單一的類 該類提供了客戶端請求的簡化 和對現(xiàn)有系統(tǒng)類 的委托調(diào)用意圖 為子系統(tǒng)中的一組接口提供一個一致的界面 外觀模式定義了一個 接口 這個接口使得這一子系統(tǒng)更加容易使用主要解決 降低 復(fù)雜系統(tǒng)的時的復(fù)雜度 簡化客戶端與之的接口何時使用 1、客戶端不需要知道系統(tǒng)內(nèi)部的復(fù)雜整個系統(tǒng)只需提供一個"接待員"即可 2、定義系統(tǒng)的如何解決 客戶端不耦合 外觀類耦合關(guān)鍵代碼 在客戶端和復(fù)雜系統(tǒng)之間再加一層 這一層將調(diào)用順序、依賴 等處理好應(yīng)用實例 1、去醫(yī)院看病 可能要去掛號、門診、劃價、取藥 讓患者或患者家屬覺得很復(fù)雜 如果有提供接待只讓接待 來處理 就很方便 2、JAVA 的三層開發(fā)模式優(yōu)點 1、減少系統(tǒng)相互依賴 2、提高靈活性 3、提高了安全性缺點 不符合開閉原則 如果要改東西很麻煩 繼承重寫都不合適使用場景 1、為復(fù)雜的模塊或子系統(tǒng)提供外界 的模塊 2、子系統(tǒng)相對注意事項 在層次化結(jié)構(gòu)中 可以使用外觀模式定義系統(tǒng)中每一層的3、預(yù)防低水平 帶來的風(fēng)險作者回復(fù)2018-06-07不錯 業(yè)務(wù)系統(tǒng)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論