Java面試題沖刺第十五天--設(shè)計(jì)模式
面試題1:面向?qū)ο蟪绦蛟O(shè)計(jì)(OOP)的六大原則分別有哪幾個(gè)
開閉原則(Open Close Principle)及“開放-封閉原則”單一職責(zé)原則(Single Responsibility Principle)里氏替換原則(Liskov Substitution Principle)依賴倒置原則(Dependence Inversion Principle)接口隔離原則(Interface Segregation Principle)最少知識(shí)原則(Law Of Demeter)
面向?qū)ο蟪绦蛟O(shè)計(jì)中,需要遵守的原則主要有6個(gè),稱為六大原則。面向?qū)ο蟪绦蛟O(shè)計(jì)原則也是我們用于評(píng)價(jià)一個(gè)設(shè)計(jì)模式的重要指標(biāo)之一。在設(shè)計(jì)模式中,很多設(shè)計(jì)模式都遵守了這些原則。
| 原則名稱 | 內(nèi)容說明 |
|---|---|
| 開閉原則 | 對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。 |
| 單一職責(zé)原則 | 即一個(gè)類只負(fù)責(zé)相應(yīng)領(lǐng)域的職責(zé),即不要存在多于一個(gè)導(dǎo)致類變更的原因。 |
| 里氏代換原則 | 子類型必須能夠替換它們的父類型。一個(gè)軟件實(shí)體如果使用的是一個(gè)父類,那么當(dāng)把這個(gè)父類替換成繼承該父類的子類,程序的行為不會(huì)發(fā)生任何變化。軟件實(shí)體察覺不出父類對(duì)象和子類對(duì)象的區(qū)別。 |
| 依賴倒置原則 | 要依賴于抽象,不要依賴于具體??蛻舳艘蕾囉诔橄篑詈稀3橄蟛粦?yīng)當(dāng)依賴于細(xì)節(jié);細(xì)節(jié)應(yīng)當(dāng)依賴于抽象;要針對(duì)接口編程,不針對(duì)實(shí)現(xiàn)編程。 |
| 接口隔離原則 | 客戶端不應(yīng)該依賴它不需要的接口。一個(gè)類對(duì)另一個(gè)類的依賴應(yīng)該建立在最小的接口上。 |
| 最少知識(shí)原則 | 對(duì)象與對(duì)象之間應(yīng)該使用盡可能少的方法來關(guān)聯(lián),避免千絲萬縷的關(guān)系。 |
面試題2:你說一下什么是設(shè)計(jì)模式
設(shè)計(jì)模式(Design pattern) 是解決軟件開發(fā)某些特定問題而提出的一些解決方案也可以理解成解決問題的一些思路。通過設(shè)計(jì)模式可以幫助我們?cè)鰪?qiáng)代碼的可重用性、可擴(kuò)充性、 可維護(hù)性、靈活性。我們使用設(shè)計(jì)模式最終的目的是實(shí)現(xiàn)代碼的 高內(nèi)聚 和低耦合。
追問1:那你怎么理解高內(nèi)聚和低耦合?
耦合:
也稱塊間聯(lián)系。指軟件系統(tǒng)結(jié)構(gòu)中各模塊間相互聯(lián)系緊密程度的一種度量。模塊之間聯(lián)系越緊密,其耦合性就越強(qiáng),模塊的獨(dú)立性則越差。
內(nèi)聚:
故名思議,表示內(nèi)部間聚集、關(guān)聯(lián)的程度,那么高內(nèi)聚就是指要高度的聚集和關(guān)聯(lián)。內(nèi)聚是從功能角度來度量模塊內(nèi)的聯(lián)系,一個(gè)好的內(nèi)聚模塊應(yīng)當(dāng)恰好做一件事。它描述的是模塊內(nèi)的功能聯(lián)系。
高內(nèi)聚低耦合,是軟件工程中的概念,是判斷軟件設(shè)計(jì)好壞的標(biāo)準(zhǔn),主要用于程序的面向?qū)ο蟮脑O(shè)計(jì),主要看類的內(nèi)聚性是否高,耦合度是否低。目的是使程序模塊的可重用性、移植性大大增強(qiáng)。通常程序結(jié)構(gòu)中各模塊的內(nèi)聚程度越高,模塊間的耦合程度就越低。
面試題3:設(shè)計(jì)模式有哪幾種?
總體來說設(shè)計(jì)模式分為三大類:
- 創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
- 結(jié)構(gòu)型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
- 行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責(zé)任鏈模式、命令模式、備忘錄模式、狀態(tài)模式、訪問者模式、中介者模式、解釋器模式。
除了23種常見設(shè)計(jì)模式外,其實(shí)還有兩類:并發(fā)型模式和線程池模式。
| 模式類型 | 名稱 | 定義 |
|---|---|---|
| 創(chuàng)建型 | 工廠方法模式(Factory Pattern) | 定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪個(gè)類。工廠方法模式是一個(gè)類的實(shí)例化延遲到子類。 |
| 創(chuàng)建型 | 抽象工廠模式(Abstract Factory Pattern) | 提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無須指定它們具體的類。 |
| 創(chuàng)建型 | 單例模式(Singleton Pattern) | 確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例,這個(gè)類稱為單例類,它提供全局訪問的方法。 |
| 創(chuàng)建型 | 建造者模式(Builder Pattern) | 將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。 |
| 創(chuàng)建型 | 原型模式(Prototype Pattern) | 用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并通過拷貝這些原型創(chuàng)建新的對(duì)象。 |
| 結(jié)構(gòu)型 | 適配器模式(Adapter Pattern) | 將一個(gè)接口轉(zhuǎn)換成客戶希望的另一個(gè)接口,使接口不兼容的那些類可以一起工作 |
| 結(jié)構(gòu)型 | 橋接模式(Bridge Pattern) | 將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。 |
| 結(jié)構(gòu)型 | 組合模式(Composite Pattern) | 組合多個(gè)對(duì)象形成樹形結(jié)構(gòu)以表示具有“整體—部分”關(guān)系的層次結(jié)構(gòu)。使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。 |
| 結(jié)構(gòu)型 | 裝飾器模式(Decorator Pattern) | 動(dòng)態(tài)地給一個(gè)對(duì)象增加一些額外的職責(zé),就增加對(duì)象功能來說,裝飾模式比生成子類實(shí)現(xiàn)更為靈活。 |
| 結(jié)構(gòu)型 | 外觀模式(Facade Pattern) | 為子系統(tǒng)中的一組接口提供一個(gè)統(tǒng)一的入口。外觀模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用 |
| 結(jié)構(gòu)型 | 享元模式(Flyweight Pattern) | 運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度對(duì)象的復(fù)用。 |
| 結(jié)構(gòu)型 | 代理模式(Proxy Pattern) | 為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。 |
| 行為型 | 責(zé)任鏈模式(Chain of Responsibility Pattern) | 使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求發(fā)送者與接收者耦合在一起。將這些對(duì)象連接成一條鏈,并且沿著這條鏈傳遞請(qǐng)求,直到有對(duì)象處理它為止。 |
| 行為型 | 命令模式(Command Pattern) | 將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志,以及支持可撤銷的操作。 |
| 行為型 | 解釋器模式(Interpreter Pattern) | 給定一個(gè)語言,定義它的文法的一種表示,并定義一個(gè)解釋器,這個(gè)解釋器使用該表示來解釋語言中的句子。 |
| 行為型 | 迭代器模式(Iterator Pattern) | 提供一種方法來訪問聚合對(duì)象中的各個(gè)元素,而不用暴露這個(gè)對(duì)象的內(nèi)部表示。 |
| 行為型 | 中介者模式(Mediator Pattern) | 用一個(gè)中介對(duì)象來封裝一系列的對(duì)象交互,中介者使各對(duì)象不需要顯式地相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互。 |
| 行為型 | 備忘錄模式(Memento Pattern) | 在不破壞封裝的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài),這樣可以在以后將對(duì)象恢復(fù)到原先保存的狀態(tài)。 |
| 行為型 | 觀察者模式(Observer Pattern) | 定義對(duì)象間的一種一對(duì)多依賴關(guān)系,使得每當(dāng)一個(gè)對(duì)象狀態(tài)發(fā)生改變時(shí),其相關(guān)依賴對(duì)象皆得到通知并被自動(dòng)更新。 |
| 行為型 | 狀態(tài)模式(State Pattern) | 允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為,對(duì)象看起來似乎修改了它的類。 |
| 行為型 | 策略模式(Strategy Pattern) | 定義一系列算法,將每一個(gè)算法封裝起來,并讓它們可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而變化。 |
| 行為型 | 模板方法模式(Template Pattern) | 定義一個(gè)操作中算法的框架,而將一些步驟延遲到子類中。模板方法模式使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。 |
| 行為型模式 | 訪問者模式(Visitor Pattern) | 表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作,它使我們可以在不改變各元素的類的前提下定義作用于這些元素的新操作。 |
追問1:你比較熟悉哪種設(shè)計(jì)模式?說說原理。
面試者老王:我都略懂一些。
面試官:那你走吧,簡歷還你。

面試者老王:???
面試者老王:那我比較了解工廠、單例、代理和適配器模式。
追問2:那你說說適配器模式的原理吧
二狗不知道在哪聽說華為手機(jī)就是牛,非要新買了一個(gè)華為手機(jī),它高高興興的拿到新手機(jī),想要插上耳機(jī)聽歌,但發(fā)現(xiàn)手機(jī)沒有通用的原型耳機(jī)孔,仔細(xì)看了說明書之后發(fā)現(xiàn),華為手機(jī)是充電孔耳機(jī)孔在一起,在插耳機(jī)時(shí)需要一個(gè)耳機(jī)口轉(zhuǎn)接器,才能插耳機(jī)。我們用程序員的眼觀來看,這里相當(dāng)于增加了一個(gè)轉(zhuǎn)接器類用于適配耳機(jī),這就類似于設(shè)計(jì)模式 —— 適配器模式(Adapter)。
適配器模式包裝目標(biāo)類即適配者(Adaptee)成適配器。適配器提供客戶端所需要的接口,把客戶端的請(qǐng)求轉(zhuǎn)化成對(duì)適配者的調(diào)用。也就是說,客戶端訪問適配器時(shí),在適配器內(nèi)部將調(diào)用適配者的方法。

- Client:客戶端,調(diào)用自己需要的接口
- TargetTarget:定義客戶端需要的跟特定需求相關(guān)的接口
- Apaptee:已存在接口,通常滿足功能需求但與特定需求接口不一致
- Adapter:適配器,將Adaptee適配為Client需要的Target接口。
適配器模式的主要功能是進(jìn)行轉(zhuǎn)換匹配,用來復(fù)用已有的功能。適配器模式將某個(gè)類的接口轉(zhuǎn)換成客戶端期望的另一個(gè)接口,目的是消除由于接口不匹配所造成的類的兼容性問題。主要分為三類:類適配器模式、對(duì)象適配器模式、接口適配器模式。
三種適配器模式有各自的應(yīng)用場(chǎng)景:
- 類的適配器模式:將一個(gè)類轉(zhuǎn)換成滿足另一個(gè)新接口的類,創(chuàng)建一個(gè)新類,繼承原有的類,實(shí)現(xiàn)新的接口即可。
- 對(duì)象的適配器模式:將一個(gè)對(duì)象轉(zhuǎn)換成滿足另一個(gè)新接口的對(duì)象,可以創(chuàng)建一個(gè)Wrapper類,持有原類的一個(gè)實(shí)例,在Wrapper類的方法中,調(diào)用實(shí)例的方法即可。
- 接口的適配器模式:當(dāng)不希望實(shí)現(xiàn)一個(gè)接口中所有的方法時(shí),可以創(chuàng)建一個(gè)抽象類Wrapper,實(shí)現(xiàn)所有方法,我們寫別的類的時(shí)候,繼承抽象類即可。
適配器模式的本質(zhì)是:轉(zhuǎn)換匹配,復(fù)用功能。適配器模式中被適配的接口Adaptee與適配的接口Target沒有關(guān)系,他們中的方法可以相同,也可以完全不同,適配器模式的實(shí)現(xiàn)方式是通過組合對(duì)象的方式進(jìn)行的,將功能委托給被適配的對(duì)象進(jìn)行的。適配器模式調(diào)用的序列圖如下所示:

適配器模式的實(shí)現(xiàn)有以下幾種:
- 常見適配:適配器類會(huì)實(shí)現(xiàn)接口,在實(shí)現(xiàn)過程中調(diào)用待適配的類中的方法
- 智能適配器:在適配器類中實(shí)現(xiàn)接口中定義的新方法,通常來說,適配器類中既可以通過借助繼承類中的方法實(shí)現(xiàn)高層功能,也可以實(shí)現(xiàn)接口中定義的新方法,進(jìn)行功能擴(kuò)展。
- 缺省適配:即對(duì)接口的缺省實(shí)現(xiàn),即接口適配器模式。
此外,在適配過程中,可能接口功能的實(shí)現(xiàn)需要多個(gè)待適配類中的方法交互才能滿足需求,即同時(shí)適配多個(gè)類。適配實(shí)現(xiàn)的復(fù)雜度取決于待適配類與接口的相似度,相似程度越高,適配類的實(shí)現(xiàn)難度越低。
在實(shí)際項(xiàng)目過程中,通常會(huì)存在兩個(gè)版本共存的情況,這就是需要使用到雙向適配器。
兩個(gè)版本的實(shí)現(xiàn)代碼:
public interface Targetable1 {
public void produce1();
}
public class Target1 implements Targetable1 {
@Override
public void produce1() {
System.out.println("Targetable1的produce1實(shí)現(xiàn)");
}
}
public interface Targetable2 {
public void produce2();
}
public class Target2 implements Targetable2 {
@Override
public void produce2() {
System.out.println("Targetable2的produce2實(shí)現(xiàn)");
}
}
適配器類的代碼如下:
public class Adapter implements Targetable1, Targetable2 {
private Targetable1 target1;
private Targetable2 target2;
@Override
public void produce1() {
target1.produce1();
}
@Override
public void produce2() {
target2.produce2();
}
}
實(shí)際上,在使用適配器過程中存在一個(gè)問題:被適配的對(duì)象不兼容Adapter適配器類,這使得適配器類的適用范圍受到限制。而雙向適配器則解決了這樣的問題,可以滿足不同客戶采用不同方式查看同一不同對(duì)象的需求。
適配器模式優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 更好的復(fù)用性。適配器模式可復(fù)用已實(shí)現(xiàn)接口的兼容。
- 更好的擴(kuò)展性。實(shí)現(xiàn)適配器的過程中可以調(diào)用自己開發(fā)的功能,實(shí)現(xiàn)系統(tǒng)的擴(kuò)展。
缺點(diǎn):
過多使用適配器,系統(tǒng)會(huì)比較混亂,不易理解。
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java List的sort()方法改寫compare()實(shí)現(xiàn)升序,降序,倒序的案例
這篇文章主要介紹了Java List的sort()方法改寫compare()實(shí)現(xiàn)升序,降序,倒序的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03
springboot中使用Hibernate-Validation校驗(yàn)參數(shù)詳解
這篇文章主要為大家介紹了springboot中使用Hibernate-Validation校驗(yàn)參數(shù)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
SpringBoot3集成SLF4J+logback進(jìn)行日志記錄的實(shí)現(xiàn)
本文主要介紹了SpringBoot3集成SLF4J+logback進(jìn)行日志記錄的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
Java線程池ThreadPoolExecutor的使用及其原理詳細(xì)解讀
這篇文章主要介紹了Java線程池ThreadPoolExecutor的使用及其原理詳細(xì)解讀,線程池是一種多線程處理形式,處理過程中將任務(wù)添加到隊(duì)列,然后在創(chuàng)建線程后自動(dòng)啟動(dòng)這些任務(wù),線程池線程都是后臺(tái)線程,需要的朋友可以參考下2023-12-12
java實(shí)現(xiàn)線上環(huán)境遠(yuǎn)程debug調(diào)試過程
本文介紹了在Docker容器中配置Tomcat和Spring Boot進(jìn)行遠(yuǎn)程調(diào)試的方法,通過配置`CATALINA_OPTS`或`JPDA`參數(shù),可以在測(cè)試環(huán)境中啟動(dòng)Tomcat或Spring Boot應(yīng)用的debug模式,然后在本地IDEA中設(shè)置斷點(diǎn)進(jìn)行調(diào)試,從而更高效地定位和解決問題2025-02-02
java向上轉(zhuǎn)型發(fā)生的時(shí)機(jī)知識(shí)點(diǎn)詳解
在本篇文章里小編給大家整理分享的是關(guān)于java向上轉(zhuǎn)型發(fā)生的時(shí)機(jī)知識(shí)點(diǎn)內(nèi)容,有興趣的讀者們可以參考下。2021-05-05

