2019秋招:460道Java後端面試高頻題答案版【模塊七:設計模式】
- 2019 年 10 月 11 日
- 筆記
寫在前面
1. 設計模式雖然在面試中沒有計算機網絡協議和操作系統那麼重要,但是也是會被經常問到的。設計模式除了在 JDK 和一些框架中被大量使用到外,在日常開發中也是很常見的。舉個我實習遇到的例子:之前實習做過訂單詳情頁,詳情頁有很多的按鈕,比如:取消訂單、再次購買、查看物流等等,我們就可以創建一個 ButtonFactory,然後根據不同的業務類型及訂單狀態進行頁面按鈕的組裝工作。這樣就避免了每種業務類型都需要創建一個按鈕組裝類的複雜工作,代碼也顯得清爽很多。
2. 這裡我推薦兩本本書,《大話設計模式》和《設計模式之禪》,這兩本書寫的都非常通俗易懂,看起來也非常快,所以還是比較推薦大家看一看的。

3. 我之前學習設計模式的時候還看了劉偉博客中關於設計模式的講解,當時自己將其博客中主要內容總結成了筆記,還有自己的代碼實現。現在雲盤中分享給大家,需要的自取:
鏈接:
https://pan.baidu.com/s/1EOn4tzFqAbtdnlW5gCW5hg
提取碼:eay4

4. 現在分享一個個人認為快速搞定設計模式的方法:設計模式不比操作系統和網絡協議必須沒有任何知識點遺漏。如果你現在時間很充足,當然建議 23 種設計模式都認真的學習下。那麼如果你現在時間很緊張了,其實可以看看面經中面試官常問到的設計模式其實也就那麼幾種:單例、工廠、適配器、裝飾器、代理、組合、策略、模板等。你可以選取其中幾種認真了解下,往自己的項目中套一套。個人感覺並不需要 23 種都熟記於心,只要能說出來自己用過的幾種就行。
5. 對於設計模式而言,我認為在面試中經常遇到的問題有以下幾種:
(1)簡單說下你了解的設計模式;
(2)你寫代碼過程中使用過設計模式嗎?我覺得這塊是可以加分的點,以為如果你會考慮使用設計模式去優化代碼,那麼說明你是有自己設計思考的,會讓面試官覺得你並不是實現功能型選手;
(3)舉例說明 JDK 源碼或者 Spring/Mybatis 框架中使用到的設計模式,這是在考察你有沒有看過相應模塊的源碼;
(4)可能會讓你對比兩種相近設計模式的區別;
(5)再有就是有時候筆試會出一些設計模式的選擇題,都是概念性的,理解即可。
1、說下你知道的設計模式有哪些?
下面 3 種類型中各挑幾個常見的或者你用過的說就可以了。

2、工廠方法模式和抽象工廠模式有什麼區別?
- 工廠方法模式:
一個抽象產品類,可以派生出多個具體產品類。 一個抽象工廠類,可以派生出多個具體工廠類。每個具體工廠類只能創建一個具體產品類的實例。
- 抽象工廠模式:
多個抽象產品類,每個抽象產品類可以派生出多個具體產品類。 一個抽象工廠類,可以派生出多個具體工廠類。每個具體工廠類可以創建多個具體產品類的實例。
- 區別:
工廠方法模式只有一個抽象產品類,而抽象工廠模式有多個。工廠方法模式的具體工廠類只能創建一個具體產品類的實例,而抽象工廠模式可以創建多個。
3、JDK 中用到了哪些設計模式?
幾乎每一種設計模式都被用到了 JDK 的源碼中,下面列舉一些常見的:
- 抽象工廠模式
1. javax.xml.parsers.DocumentBuilderFactory#newInstance() 2. javax.xml.transform.TransformerFactory#newInstance()
- 建造者模式
1. java.lang.StringBuilder#append() 2. java.lang.StringBuffer#append()
- 原型模式
1. java.lang.Object#clone()
- 適配器模式
1. java.util.Arrays#asList() 2. java.util.Collections#list()
- 裝飾器模式
1. IO 流的子類 2. java.util.Collections#synchronizedXXX()
- 享元模式
1. java.lang.Integer#valueOf(int)
- 代理模式
1. java.lang.reflect.Proxy 2. javax.inject.Inject
- 責任鏈模式
1. java.util.logging.Logger#log() 2. javax.servlet.Filter#doFilter()
……
4、Spring 中用到了哪些設計模式?
1. 單例設計模式 : Spring 中的 Bean 默認都是單例的;
2. 代理設計模式 : Spring AOP 功能的實現;
3. 工廠設計模式 : Spring 使用工廠模式通過 BeanFactory、ApplicationContext 創建 Bean 對象;
4. 模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 結尾的對數據庫操作的類,它們就使用到了模板模式;
5. 裝飾器設計模式 : 我們的項目需要連接多個數據庫,而且不同的客戶在每次訪問中根據需要會去訪問不同的數據庫。這種模式讓我們可以根據客戶的需求能夠動態切換不同的數據源;
6. 觀察者模式:Spring 事件驅動模型就是觀察者模式很經典的一個應用;
7. 適配器模式:Spring AOP 的增強或通知(Advice)使用到了適配器模式、SpringMVC 中也是用到了適配器模式適配 Controller。
5、設計模式六大原則是什麼?
1. 單一職責原則:一個方法 一個類只負責一個職責,各個職責的程序改動,不影響其它程序。
2. 開閉原則:對擴展開放,對修改關閉。即在不修改一個軟件實體的基礎上去擴展其他功能。
3. 里氏代換原則:在軟件系統中,一個可以接受基類對象的地方必然可以接受一個子類對象。
4. 依賴倒轉原則:針對於接口編程,依賴於抽象而不依賴於具體。
5. 接口隔離原則:使用多個隔離的接口取代一個統一的接口。降低類與類之間的耦合度。
6. 迪米特原則:一個實體應當盡量少的與其他實體之間發生相互作用,使得系統功能模塊相對獨立。
7. 單例模式的優缺點?
- 優點:
由於在系統內存中只存在一個對象,因此可以節約系統資源,對於一些需要頻繁創建和銷毀的對象單例模式無疑可以提高系統的性能。
- 缺點:
由於單例模式中沒有抽象層,因此單例類的擴展有很大的困難。濫用單例將帶來一些負面問題,如為了節省資源將數據庫連接池對象設計為的單例類,可能會導致共享連接池對象的程序過多而出現連接池溢出;如果實例化的對象長時間不被利用,系統會認為是垃圾而被回收,這將導致對象狀態的丟失。
8、請手寫一下單例模式?
- 1. 懶漢式:用到時再去創建
public class Singleton { private static Singleton instance; private Singleton(){}; public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
- 2. 餓漢式:初始化時即創建,用到時直接返回
public class Singleton { private static Singleton instance = new Singleton(); private Singleton(){}; public static Singleton getInstance(){ return instance; } }
- 3. 靜態內部類【推薦】
public class Singleton { private static class SingletonHolder{ private static final Singleton INSTTANCE = new Singleton(); } private Singleton(){}; public static final Singleton getInstance(){ return SingletonHolder.INSTTANCE; } }
- 4. 雙重校驗鎖【推薦】
public class Singleton { private volatile static Singleton singleton; private Singleton(){}; public static Singleton getSingleton(){ if(singleton == null){ synchronized(Singleton.class){ if(singleton == null){ singleton = new Singleton(); } } } return singleton; } }
9、樹形文件目錄採用的是哪種設計模式?
採用的是組合模式。樹形結構在軟件中隨處可見,例如:操作系統中的目錄結構、應用軟件中的菜單、辦公系統中的公司組織結構等等,如何運用面向對象的方式來處理這種樹形結構是組合模式需要解決的問題,組合模式通過一種巧妙的設計方案使得用戶可以一致性地處理整個樹形結構或者樹形結構的一部分,也可以一致性地處理樹形結構中的葉子節點(不包含子節點的節點)和容器節點(包含子節點的節點)。