Java面試題沖刺第十五天–設計模式

面試題1:面向對象程序設計(OOP)的六大原則分別有哪幾個

開閉原則(Open Close Principle)及“開放-封閉原則”單一職責原則(Single Responsibility Principle)裡氏替換原則(Liskov Substitution Principle)依賴倒置原則(Dependence Inversion Principle)接口隔離原則(Interface Segregation Principle)最少知識原則(Law Of Demeter)

面向對象程序設計中,需要遵守的原則主要有6個,稱為六大原則。面向對象程序設計原則也是我們用於評價一個設計模式的重要指標之一。在設計模式中,很多設計模式都遵守瞭這些原則。

原則名稱 內容說明
開閉原則 對擴展開放,對修改關閉。
單一職責原則 即一個類隻負責相應領域的職責,即不要存在多於一個導致類變更的原因。
裡氏代換原則 子類型必須能夠替換它們的父類型。一個軟件實體如果使用的是一個父類,那麼當把這個父類替換成繼承該父類的子類,程序的行為不會發生任何變化。軟件實體察覺不出父類對象和子類對象的區別。
依賴倒置原則 要依賴於抽象,不要依賴於具體。客戶端依賴於抽象耦合。抽象不應當依賴於細節;細節應當依賴於抽象;要針對接口編程,不針對實現編程。
接口隔離原則 客戶端不應該依賴它不需要的接口。一個類對另一個類的依賴應該建立在最小的接口上。
最少知識原則 對象與對象之間應該使用盡可能少的方法來關聯,避免千絲萬縷的關系。

面試題2:你說一下什麼是設計模式

設計模式(Design pattern) 是解決軟件開發某些特定問題而提出的一些解決方案也可以理解成解決問題的一些思路。通過設計模式可以幫助我們增強代碼的可重用性、可擴充性、 可維護性、靈活性。我們使用設計模式最終的目的是實現代碼的 高內聚 和低耦合。

追問1:那你怎麼理解高內聚和低耦合?

耦合:

也稱塊間聯系。指軟件系統結構中各模塊間相互聯系緊密程度的一種度量。模塊之間聯系越緊密,其耦合性就越強,模塊的獨立性則越差。

內聚:

故名思議,表示內部間聚集、關聯的程度,那麼高內聚就是指要高度的聚集和關聯。內聚是從功能角度來度量模塊內的聯系,一個好的內聚模塊應當恰好做一件事。它描述的是模塊內的功能聯系。

高內聚低耦合,是軟件工程中的概念,是判斷軟件設計好壞的標準,主要用於程序的面向對象的設計,主要看類的內聚性是否高,耦合度是否低。目的是使程序模塊的可重用性、移植性大大增強。通常程序結構中各模塊的內聚程度越高,模塊間的耦合程度就越低。

面試題3:設計模式有哪幾種?

總體來說設計模式分為三大類:

  • 創建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
  • 結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
  • 行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。

除瞭23種常見設計模式外,其實還有兩類:並發型模式和線程池模式。

模式類型 名稱 定義
創建型 工廠方法模式(Factory Pattern) 定義一個用於創建對象的接口,讓子類決定實例化哪個類。工廠方法模式是一個類的實例化延遲到子類。
創建型 抽象工廠模式(Abstract Factory Pattern) 提供一個創建一系列相關或相互依賴對象的接口,而無須指定它們具體的類。
創建型 單例模式(Singleton Pattern) 確保某一個類隻有一個實例,而且自行實例化並向整個系統提供這個實例,這個類稱為單例類,它提供全局訪問的方法。
創建型 建造者模式(Builder Pattern) 將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
創建型 原型模式(Prototype Pattern) 用原型實例指定創建對象的種類,並通過拷貝這些原型創建新的對象。
結構型 適配器模式(Adapter Pattern) 將一個接口轉換成客戶希望的另一個接口,使接口不兼容的那些類可以一起工作
結構型 橋接模式(Bridge Pattern) 將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
結構型 組合模式(Composite Pattern) 組合多個對象形成樹形結構以表示具有“整體—部分”關系的層次結構。使得用戶對單個對象和組合對象的使用具有一致性。
結構型 裝飾器模式(Decorator Pattern) 動態地給一個對象增加一些額外的職責,就增加對象功能來說,裝飾模式比生成子類實現更為靈活。
結構型 外觀模式(Facade Pattern) 為子系統中的一組接口提供一個統一的入口。外觀模式定義瞭一個高層接口,這個接口使得這一子系統更加容易使用
結構型 享元模式(Flyweight Pattern) 運用共享技術有效地支持大量細粒度對象的復用。
結構型 代理模式(Proxy Pattern) 為其他對象提供一種代理以控制對這個對象的訪問。
行為型 責任鏈模式(Chain of Responsibility Pattern) 使多個對象都有機會處理請求,從而避免請求發送者與接收者耦合在一起。將這些對象連接成一條鏈,並且沿著這條鏈傳遞請求,直到有對象處理它為止。
行為型 命令模式(Command Pattern) 將一個請求封裝為一個對象,從而可用不同的請求對客戶進行參數化;對請求排隊或者記錄請求日志,以及支持可撤銷的操作。
行為型 解釋器模式(Interpreter Pattern) 給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
行為型 迭代器模式(Iterator Pattern) 提供一種方法來訪問聚合對象中的各個元素,而不用暴露這個對象的內部表示。
行為型 中介者模式(Mediator Pattern) 用一個中介對象來封裝一系列的對象交互,中介者使各對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨立地改變它們之間的交互。
行為型 備忘錄模式(Memento Pattern) 在不破壞封裝的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態,這樣可以在以後將對象恢復到原先保存的狀態。
行為型 觀察者模式(Observer Pattern) 定義對象間的一種一對多依賴關系,使得每當一個對象狀態發生改變時,其相關依賴對象皆得到通知並被自動更新。
行為型 狀態模式(State Pattern) 允許一個對象在其內部狀態改變時改變它的行為,對象看起來似乎修改瞭它的類。
行為型 策略模式(Strategy Pattern) 定義一系列算法,將每一個算法封裝起來,並讓它們可以相互替換。策略模式讓算法獨立於使用它的客戶而變化。
行為型 模板方法模式(Template Pattern) 定義一個操作中算法的框架,而將一些步驟延遲到子類中。模板方法模式使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
行為型模式 訪問者模式(Visitor Pattern) 表示一個作用於某對象結構中的各元素的操作,它使我們可以在不改變各元素的類的前提下定義作用於這些元素的新操作。

追問1:你比較熟悉哪種設計模式?說說原理。

面試者老王:我都略懂一些。

面試官:那你走吧,簡歷還你。

在這裡插入圖片描述

面試者老王:???

面試者老王:那我比較瞭解工廠、單例、代理和適配器模式。

追問2:那你說說適配器模式的原理吧

二狗不知道在哪聽說華為手機就是牛,非要新買瞭一個華為手機,它高高興興的拿到新手機,想要插上耳機聽歌,但發現手機沒有通用的原型耳機孔,仔細看瞭說明書之後發現,華為手機是充電孔耳機孔在一起,在插耳機時需要一個耳機口轉接器,才能插耳機。我們用程序員的眼觀來看,這裡相當於增加瞭一個轉接器類用於適配耳機,這就類似於設計模式 —— 適配器模式(Adapter)。

適配器模式包裝目標類即適配者(Adaptee)成適配器。適配器提供客戶端所需要的接口,把客戶端的請求轉化成對適配者的調用。也就是說,客戶端訪問適配器時,在適配器內部將調用適配者的方法。

在這裡插入圖片描述

  • Client:客戶端,調用自己需要的接口
  • TargetTarget:定義客戶端需要的跟特定需求相關的接口
  • Apaptee:已存在接口,通常滿足功能需求但與特定需求接口不一致
  • Adapter:適配器,將Adaptee適配為Client需要的Target接口。

適配器模式的主要功能是進行轉換匹配,用來復用已有的功能。適配器模式將某個類的接口轉換成客戶端期望的另一個接口,目的是消除由於接口不匹配所造成的類的兼容性問題。主要分為三類:類適配器模式、對象適配器模式、接口適配器模式。

三種適配器模式有各自的應用場景:

  • 類的適配器模式:將一個類轉換成滿足另一個新接口的類,創建一個新類,繼承原有的類,實現新的接口即可。
  • 對象的適配器模式:將一個對象轉換成滿足另一個新接口的對象,可以創建一個Wrapper類,持有原類的一個實例,在Wrapper類的方法中,調用實例的方法即可。
  • 接口的適配器模式:當不希望實現一個接口中所有的方法時,可以創建一個抽象類Wrapper,實現所有方法,我們寫別的類的時候,繼承抽象類即可。

適配器模式的本質是:轉換匹配,復用功能。適配器模式中被適配的接口Adaptee與適配的接口Target沒有關系,他們中的方法可以相同,也可以完全不同,適配器模式的實現方式是通過組合對象的方式進行的,將功能委托給被適配的對象進行的。適配器模式調用的序列圖如下所示:

在這裡插入圖片描述

適配器模式的實現有以下幾種:

  • 常見適配:適配器類會實現接口,在實現過程中調用待適配的類中的方法
  • 智能適配器:在適配器類中實現接口中定義的新方法,通常來說,適配器類中既可以通過借助繼承類中的方法實現高層功能,也可以實現接口中定義的新方法,進行功能擴展。
  • 缺省適配:即對接口的缺省實現,即接口適配器模式。

此外,在適配過程中,可能接口功能的實現需要多個待適配類中的方法交互才能滿足需求,即同時適配多個類。適配實現的復雜度取決於待適配類與接口的相似度,相似程度越高,適配類的實現難度越低。

在實際項目過程中,通常會存在兩個版本共存的情況,這就是需要使用到雙向適配器。

兩個版本的實現代碼:

public interface Targetable1 {
	public void produce1();
}
public class Target1 implements Targetable1 {
	@Override
	public void produce1() {
		System.out.println("Targetable1的produce1實現");
	}
}

public interface Targetable2 {
	public void produce2();
}
public class Target2 implements Targetable2 {
	@Override
	public void produce2() {
		System.out.println("Targetable2的produce2實現");
	}
}

適配器類的代碼如下:

public class Adapter implements Targetable1, Targetable2 {

    private Targetable1 target1;
    private Targetable2 target2;

    @Override
    public void produce1() {
        target1.produce1();
    }

    @Override
    public void produce2() {
        target2.produce2();
    }
}

實際上,在使用適配器過程中存在一個問題:被適配的對象不兼容Adapter適配器類,這使得適配器類的適用范圍受到限制。而雙向適配器則解決瞭這樣的問題,可以滿足不同客戶采用不同方式查看同一不同對象的需求。

適配器模式優缺點

優點:

  • 更好的復用性。適配器模式可復用已實現接口的兼容。
  • 更好的擴展性。實現適配器的過程中可以調用自己開發的功能,實現系統的擴展。

缺點:

過多使用適配器,系統會比較混亂,不易理解。

總結

本篇文章就到這裡瞭,希望能給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: