1.請(qǐng)列舉出在 JDK 中幾個(gè)常用的設(shè)計(jì)模式进统?
單例模式(Singleton pattern)用于 Runtime熊赖,Calendar 和其他的一些類(lèi)中桂塞。工廠模式
(Factory pattern)被用于各種不可變的類(lèi)如 Boolean刊愚,像 Boolean.valueOf,觀察者模式
(Observer pattern)被用于 Swing 和很多的事件監(jiān)聽(tīng)中吩抓。裝飾器設(shè)計(jì)模式(Decorator
design pattern)被用于多個(gè) Java IO 類(lèi)中涉茧。
2.什么是設(shè)計(jì)模式?你是否在你的代碼里面使用過(guò)任何設(shè)計(jì)模式疹娶?
設(shè)計(jì)模式是世界上各種各樣程序員用來(lái)解決特定設(shè)計(jì)問(wèn)題的嘗試和測(cè)試的方法伴栓。設(shè)計(jì)模式
是代碼可用性的延伸
3.Java 中什么叫單例設(shè)計(jì)模式?請(qǐng)用 Java 寫(xiě)出線程安全的單例模式
單例模式重點(diǎn)在于在整個(gè)系統(tǒng)上共享一些創(chuàng)建時(shí)較耗資源的對(duì)象。整個(gè)應(yīng)用中只維護(hù)一個(gè)
特定類(lèi)實(shí)例钳垮,它被所有組件共同使用除师。Java.lang.Runtime 是單例模式的經(jīng)典例子。從 Java
5 開(kāi)始你可以使用枚舉(enum)來(lái)實(shí)現(xiàn)線程安全的單例扔枫。
4.在 Java 中,什么叫觀察者設(shè)計(jì)模式(observer design pattern)锹安?
觀察者模式是基于對(duì)象的狀態(tài)變化和觀察者的通訊短荐,以便他們作出相應(yīng)的操作。簡(jiǎn)單的例
子就是一個(gè)天氣系統(tǒng)叹哭,當(dāng)天氣變化時(shí)必須在展示給公眾的視圖中進(jìn)行反映忍宋。這個(gè)視圖對(duì)象
是一個(gè)主體,而不同的視圖是觀察者风罩。
5.使用工廠模式最主要的好處是什么糠排?在哪里使用?
工廠模式的最大好處是增加了創(chuàng)建對(duì)象時(shí)的封裝層次超升。如果你使用工廠來(lái)創(chuàng)建對(duì)象入宦,之后
你可以使用更高級(jí)和更高性能的實(shí)現(xiàn)來(lái)替換原始的產(chǎn)品實(shí)現(xiàn)或類(lèi),這不需要在調(diào)用層做任
何修改室琢。
6.舉一個(gè)用 Java 實(shí)現(xiàn)的裝飾模式(decorator design pattern)乾闰?它是作用于對(duì)象層次還是類(lèi)
層次?
裝飾模式增加強(qiáng)了單個(gè)對(duì)象的能力盈滴。Java IO 到處都使用了裝飾模式涯肩,典型例子就是
Buffered 系列類(lèi)如 BufferedReader 和 BufferedWriter,它們?cè)鰪?qiáng)了 Reader 和 Writer 對(duì)象巢钓,
以實(shí)現(xiàn)提升性能的 Buffer 層次的讀取和寫(xiě)入病苗。
7.在 Java 中,為什么不允許從靜態(tài)方法中訪問(wèn)非靜態(tài)變量症汹?
Java 中不能從靜態(tài)上下文訪問(wèn)非靜態(tài)數(shù)據(jù)只是因?yàn)榉庆o態(tài)變量是跟具體的對(duì)象實(shí)例關(guān)聯(lián)
的硫朦,而靜態(tài)的卻沒(méi)有和任何實(shí)例關(guān)聯(lián)。
8.設(shè)計(jì)一個(gè) ATM 機(jī)烈菌,請(qǐng)說(shuō)出你的設(shè)計(jì)思路阵幸?
比如設(shè)計(jì)金融系統(tǒng)來(lái)說(shuō),必須知道它們應(yīng)該在任何情況下都能夠正常工作芽世。不管是斷電還
是其他情況挚赊,ATM 應(yīng)該保持正確的狀態(tài)(事務(wù)) , 想想 加鎖(locking)、事務(wù)
(transaction)济瓢、錯(cuò)誤條件(error condition)荠割、邊界條件(boundary condition) 等等。盡管
你不能想到具體的設(shè)計(jì),但如果你可以指出非功能性需求蔑鹦,提出一些問(wèn)題夺克,想到關(guān)于邊界
條件,這些都會(huì)是很好的嚎朽。
9.在 Java 中铺纽,什么時(shí)候用重載,什么時(shí)候用重寫(xiě)哟忍?
如果你看到一個(gè)類(lèi)的不同實(shí)現(xiàn)有著不同的方式來(lái)做同一件事狡门,那么就應(yīng)該用重寫(xiě)
(overriding),而重載(overloading)是用不同的輸入做同一件事锅很。在 Java 中其馏,重載的方
法簽名不同,而重寫(xiě)并不是爆安。
10.舉例說(shuō)明什么情況下會(huì)更傾向于使用抽象類(lèi)而不是接口叛复?
接口和抽象類(lèi)都遵循”面向接口而不是實(shí)現(xiàn)編碼”設(shè)計(jì)原則,它可以增加代碼的靈活性扔仓,
可以適應(yīng)不斷變化的需求褐奥。下面有幾個(gè)點(diǎn)可以幫助你回答這個(gè)問(wèn)題:
在 Java 中,你只能繼承一個(gè)類(lèi)翘簇,但可以實(shí)現(xiàn)多個(gè)接口抖僵。所以一旦你繼承了一個(gè)類(lèi),你就
失去了繼承其他類(lèi)的機(jī)會(huì)了缘揪。
接口通常被用來(lái)表示附屬描述或行為如:Runnable耍群、Clonable、Serializable 等等找筝,因此當(dāng)你
使用抽象類(lèi)來(lái)表示行為時(shí)蹈垢,你的類(lèi)就不能同時(shí)是 Runnable 和 Clonable(注:這里的意思是指
如果把 Runnable 等實(shí)現(xiàn)為抽象類(lèi)的情況),因?yàn)樵?Java 中你不能繼承兩個(gè)類(lèi)袖裕,但當(dāng)你使用
接口時(shí)曹抬,你的類(lèi)就可以同時(shí)擁有多個(gè)不同的行為。
在一些對(duì)時(shí)間要求比較高的應(yīng)用中急鳄,傾向于使用抽象類(lèi)谤民,它會(huì)比接口稍快一點(diǎn)。
如果希望把一系列行為都規(guī)范在類(lèi)繼承層次內(nèi)疾宏,并且可以更好地在同一個(gè)地方進(jìn)行編碼张足,
那么抽象類(lèi)是一個(gè)更好的選擇。有時(shí)坎藐,接口和抽象類(lèi)可以一起使用为牍,接口中定義函數(shù)哼绑,而
在抽象類(lèi)中定義默認(rèn)的實(shí)現(xiàn)。
11.設(shè)計(jì)模式六大原則
a.單一職責(zé)原則:就一個(gè)類(lèi)來(lái)說(shuō)碉咆,應(yīng)該只有一個(gè)引起它變化的原因
一個(gè)類(lèi)做一件事情抖韩,避免職責(zé)過(guò)多。比如這種情況是不太好的疫铜,在一個(gè)Activity中既有bean文件茂浮,又有http請(qǐng)求,還有adapter等等壳咕,這就導(dǎo)致我們需要修改任何一個(gè)東西的時(shí)候都會(huì)導(dǎo)致Activity的改變励稳,這樣一來(lái)就有多個(gè)引起它變化的原因,不符合單一職責(zé)原則
b.開(kāi)放封閉原則:類(lèi)囱井,模塊,函數(shù)應(yīng)該是可以擴(kuò)展的趣避,但是不可以修改
對(duì)于擴(kuò)展是開(kāi)放的庞呕,對(duì)于修改是封閉的。盡量做到面對(duì)需求的改變時(shí)程帕,我們的代碼能保持相對(duì)穩(wěn)定住练,通過(guò)擴(kuò)展的方式應(yīng)對(duì)變化,而不是修改原有代碼實(shí)現(xiàn)
c.里氏替換原則:所有引用基類(lèi)的地方愁拭,必須可以透明的時(shí)候其子類(lèi)的對(duì)象
里氏替換原則是實(shí)現(xiàn)開(kāi)放封閉原則的重要方式之一讲逛,我們知道,使用基類(lèi)的地方都可以使用子類(lèi)去實(shí)現(xiàn)岭埠,因?yàn)樽宇?lèi)擁有基類(lèi)的所有方法盏混,所以在程序設(shè)計(jì)中盡量使用基類(lèi)類(lèi)型對(duì)對(duì)象進(jìn)行定義,在運(yùn)行時(shí)確定子類(lèi)類(lèi)型惜论。
d.依賴(lài)倒置原則:高層模塊不應(yīng)該依賴(lài)于底層模塊许赃,兩者都應(yīng)該依賴(lài)于抽象,抽象不應(yīng)該依賴(lài)于細(xì)節(jié)馆类,細(xì)節(jié)應(yīng)該依賴(lài)于抽象
依賴(lài)倒置原則針對(duì)的是模塊之間的依賴(lài)關(guān)系混聊,高層模塊指調(diào)用端,底層模塊指具體的實(shí)現(xiàn)類(lèi)乾巧,抽象指接口或抽象類(lèi)句喜,細(xì)節(jié)就是實(shí)現(xiàn)類(lèi)。該原則的具體表現(xiàn)就是模塊間的依賴(lài)通過(guò)抽象發(fā)生沟于,直線類(lèi)之間不發(fā)生直接依賴(lài)關(guān)系咳胃,依賴(lài)通過(guò)接口或抽象類(lèi)產(chǎn)生,降低耦合旷太,比如MVP模式下拙绊,View層和P層通過(guò)接口產(chǎn)生依賴(lài)關(guān)系
e.迪米特原則(最少知識(shí)原則):一個(gè)軟件實(shí)體應(yīng)該盡可能少的與其他實(shí)體發(fā)生相互作用
迪米特原則要求我們?cè)谠O(shè)計(jì)系統(tǒng)時(shí),盡量減少對(duì)象之間的交互
f.接口隔離原則:一個(gè)類(lèi)對(duì)另一個(gè)類(lèi)的依賴(lài)應(yīng)該建立在最小的接口上
接口隔離原則的關(guān)鍵是接口以及這個(gè)接口要小,如何小呢标沪,也就是我們要為專(zhuān)門(mén)的類(lèi)創(chuàng)建專(zhuān)門(mén)的接口榄攀,這個(gè)接口只對(duì)它有效,不要試圖讓一個(gè)接口包羅萬(wàn)象金句,要建立最小的依賴(lài)關(guān)系
12.設(shè)計(jì)模式的分類(lèi)
設(shè)計(jì)模式分為三類(lèi)
創(chuàng)建型設(shè)計(jì)模式
與對(duì)象創(chuàng)建有關(guān)包括單例模式檩赢,工廠方法模式,抽象工廠模式违寞,建造者模式贞瞒,原型模式
結(jié)構(gòu)型設(shè)計(jì)模式
結(jié)構(gòu)性設(shè)計(jì)模式是從程序的結(jié)構(gòu)上解決模塊之間的耦合問(wèn)題,包括適配器模式趁曼,代理模式军浆,裝飾模式,外觀模式挡闰,橋接模式乒融,組合模式和享元模式
行為型設(shè)計(jì)模式
主要處理類(lèi)或?qū)ο笕绾谓换ゼ叭绾畏峙渎氊?zé),包括策略模式摄悯,模板方法模式赞季,觀察者模式,迭代器模式奢驯,責(zé)任鏈模式申钩,命令模式,備忘錄模式瘪阁,狀態(tài)模式撒遣,訪問(wèn)者模式,中介模式管跺,解析器模式