設計模式見解

1、在java中,什麼時候用重載,什麼使用用重寫?

重載(Overloading)和重寫(Overriding)都可以對業務功能的增強。

重載: 在同一個類中,方法名一樣,但是參數不一樣(即參數的數量或參數類型不能完全相同)

重寫: 在父子類中,子類重寫了父類中的方法。需要具有相同的方法名、參數、返回值。

重載 就是在類中可以創建多個方法,它們具有相同的名字,但具有不同的參數和不同的定義。

調用方法時通過傳遞給它們的不同參數個數和參數類型來決定具體使用哪個方法, 這就是多態性。

重載中返回值類型可以相同也可以不相同。無法以返回型別作爲重載函數的區分標準。

重寫 中訪問修飾符的限制一定要大於被重寫方法的訪問修飾(public>protected>default>private)

被final修飾和private修飾的方法不能被重寫

代碼中應用: 重載:之前寫的登錄,在系統內是loginname和password兩個參數才能登錄,但是因爲業務需要跟第三方對接接口的時候,可以從他們系統直接登錄到我們系統,但是沒有loginname和password,只有根據雙方系統中都有的一個字段身份證來認證,我處理方法:根據第三方傳來的身份證號生成token並且返回,他們帶着token再次來請求。所以我要寫一個login()的重載方法。跟之前的參數不一致,只需一個參數token就可以。 重寫: 平時和同事寫一個類似的功能,所需參數一樣,返回值也一樣。就僅僅是業務處理可能不一樣,我們就會在父類中寫聲明一個方法,然後我倆同時重寫這個方法,然後各自寫自己的業務就行。

2、舉例一個你更傾向於抽象類,而不是接口的代碼設計場景

抽象類和接口都是對事物的一種抽象, 接口是對動作的一種抽象,而實現類是對根源的抽象。

接口裏定義的變量只能是公共的靜態的常量,抽象類中的變量是普通變量。

抽象方法要被實現,所以不能是靜態的,也不能是私有的。

接口可繼承接口,並可多繼承接口,但類只能單根繼承。

當業務中,有一些功能是一致的,大多時候都不會被重寫的,這時候可以使用抽象類定義一個具體的實現方法,這樣就不用子類一一實現了。例如在spring中的JDBCtemplate中就使用了抽象類作爲模板設計模式基礎。

 

3、在java中,爲什麼不允許靜態方法中訪問非靜態變量?

靜態方法只能調用靜態方法或者變量,非靜態方法只能調用非靜態方法或者變量。

一個類的靜態變量和靜態方法是屬於這個類本身的,在類被加載的時候就會分配內存(方法區),可以直接通過類名點的方式來調用, 而非靜態方法和變量是屬於對象的,也只有在外部使用這個類的對象時,比如 new 這個對象時, 非靜態變量和方法纔會被加載到堆內存中。

所以說,靜態變量和方法是優先加載的,而且只加載一次,非靜態變量和方法是外部使用的時候才被加載。 所以當靜態變量和方法加載後, 非靜態變量和方法可能沒有被加載,所以不能訪問。

在開發中我們會使用很多工具類,在寫工具類的時候我們一般都使用的是靜態方法,因爲不用每次調用的時候都要去new 出來,不用頻繁的讀寫內存, 而是從內存中直接取出來。

4、列舉你說了解的軟件分層場景,軟件分層有哪些好處?

舉例: 就像我們在開發中會將代碼分爲3層,

表現層(controller) 與前端交互數據。

業務層(service) 處理業務

持久層(dao) 與數據庫交互,一般寫sql

這樣分層可以使編寫代碼的時候各行其志,我們在各自的分層中寫對應的代碼。

經典的MVC架構:

模型(model)、視圖(view)、控制器(controller)。

模型: 關注數據的處理,主要負責業務代碼和數據操作。

視圖: 頁面。 顯示數據用的,例如 html 、jsp等。

控制器: 用於 視圖和模型 之間的協調

好處: 1、讓代碼看起來更加清晰。可維護性高。

2、模型和視圖之間的耦合性低。

5、請列舉符合開閉原則的設計模式。

先說一下開閉原則: 一個軟件實體應當對外擴展開放,對修改關閉。 即軟件實體應儘量在不修改原有的代碼情況下進行擴展。

1、適配器模式: 在適配器模式中,我們通過增加一個新的適配器類來解決接口不兼容的問題,使得原本沒有任何關係的類可以協同工作。適配器類繼承了目標抽象類,而適配器又有適配者的引用。

2、裝飾者設計模式: 裝飾者設計模式的本意就是不改變一個對象本身功能的基礎上給對象增加額外的新行爲。 裝飾模式是一種用於替代繼承的技術,在裝飾模式中引入了裝飾類,在裝飾類中既可以調用待裝飾的原有類的方法,還可以增加新的方法,以擴充原有類的功能

3、工廠方法模式:工廠方法模式引用了 抽象工廠角色。 這樣在我們添加具體的產品工廠的時候,只需要繼承或實現抽象工廠就行,不用修改原有代碼。

4、觀察者模式: 定義對象之間的一種一對多依賴關係,使得每當一個對象狀態發生改變時,其相關依賴對象皆得到通知並被自動更新。觀察者模式的別名包括髮布-訂閱。 當我們需要增加一個具體的觀察者時候,不需要修改原有的代碼, 而是只需要繼承之前定義的觀察者接口即可。

5、代理模式: 代理模式分爲JDK動態代理和cgLib動態代理, 代理模式是給某一個對象提供一個代理或佔位符,並由代理對象來控制對原對象的訪問。我們要增強某個方法的時候,只需要在代理類都完成就行,不用在原有代碼上做修改。

6、策略模式: 實現某一個功能有多條途徑,每一條途徑對應一種算法,此時我們可以使用策略模式來實現靈活地選擇解決途徑。 我們在使用策略模式的時候可以在不修改代碼的情況下 增加新的策略方式。

7、模板方法模式: 模板方法模式是一種基於繼承的代碼複用技術。 在父類中提供了一個定義算法框架的模板方法,還提供了一系列抽象方法、具體方法和鉤子方法。 我們可以通過添加不同的子類,來完善我們的需求。但是這樣有個不好的地方,就是會導致我們的子類越來越多。

6.總結設計模式中創建型、結構型、行爲型之間的根本區別?

創建型

創建型模式與對象的創建有關。

結構型

結構型模式處理類或對象的組合,它採用繼承機制來組合接口或實現(類結構型模式),或者通過組合一些對象,從而實現新的功能(對象結構型模式)

行爲型

行爲型模式對類或對象怎樣交互和怎樣分配職責進行描述

模式 創建型模式 結構型模式 行爲型模式
概念 創建型模式:就是創建對象的模式,抽象了實例化的過程。也可以理解爲將創建的對象的過程進行了封裝,作爲使用者僅僅知道怎麼樣去使用對象,而不會關心創建對象過程的邏輯 結構型模式是爲了解決怎麼樣組裝現有的類,設計它們的交互方式,從而達到實現功能的目的。 行爲型模式是對類或者對象進行交互的描述,
包含的設計模式 1、簡單工廠模式 2、工廠方法模式 3、抽象工廠模式 4、單例模式 5、原型模式 6、建造者模式 1、適配器模式 2、橋接模式 3.組合模式 4、裝飾模式 5、外觀模式 6、享元模式 7、代理模式 1、責任鏈模式 2、命令模式 3、解釋器模式 4、迭代器模式 5、中介者模式 6、備忘錄模式 7、觀察者模式 8、狀態模式 9.策略模式 10、模板方法模式 11訪問者模式

7、在構造方法中拋出異常是阻止反射破壞單例的唯一方法嘛? 爲什麼?

不是。在構造方法中拋出異常可以阻止反射破壞單例。因爲反射可以獲取到私有的構造方法,這樣就會根據構造來創建對象,破壞單例,所以在構造方法中拋出異常可以阻止反射破壞單例。如代碼:

// 構造私有化
    private LazyInnerClassSingleton(){
        //防止反射破壞單例
        if (InnerClass.lazyInnerClassSingleton != null){
            throw new RuntimeException("不允許創建多個實例");
        }
    }

當然還有其他的方式可以阻止反射破壞單例。 枚舉(註冊式單例)可以。枚舉是jdk1.5之後出現的。

所有的枚舉編譯後都繼承了Enum(抽象類)

在JDK源碼中我們可以看到反射的 Constructor的 newInstance()的代碼反射在通過newInstance創建對象時,會檢查該類是否ENUM修飾,如果是則拋出異常,反射失敗。

8、雙重檢查鎖爲何要做兩次非空檢測?

第一個判斷主要是爲了做性能優化,第二個判斷是做邏輯控制的。

 /**
    * @Param: []
    * @return: com.gitee.spring.singleton.lazy.LazyDoubleCheckSingleton
    * @Date: 2019/3/13
    * @Description:  doublecheck來解決
    */
    public static LazyDoubleCheckSingleton getInstance2(){
        //線程過來後先判斷是否已經生成了對象,如果生成了直接返回,如果沒有,線程纔會去爭搶鎖
        if (lazyDoubleCheckSingleton == null){
            synchronized (LazyDoubleCheckSingleton.class){
                // synchronized 只是鎖了這一小部分代碼。
                //這裏加判斷是因爲,假設有兩個線程。A、B 如果A現貨的鎖運行這段代碼,然後會生成
                //對象。接下來釋放鎖,然後線程B獲得鎖,此時該類已經生成過對象了,如果沒有判斷這時候
                //這時候B也會生成新的對象,則會不符合單例原則,所以需要加判斷,如果已經有了對象B線程
                //直接返回。
                if (lazyDoubleCheckSingleton == null)
                lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
            }
        }
        return lazyDoubleCheckSingleton;
    }

9、原型模式能夠給你解決的最大的麻煩是什麼?

在之前學設計模式的時候,我們都知道原型模式是一種創建型模式。通過copy這些原型來創建新的對象。

原型模式原理: 是通過克隆的方式創建一個全新的對象,全新的對象在內存中有新的地址,通常對克隆所產生的對象進行修改對原型對象不會造成任何影響,每一個克隆對象都是相互獨立的。通過不同的方式修改可以得到一系列相似但不完全相同的對象。

說到克隆又分爲兩種: 淺克隆和深克隆。

淺克隆

在淺克隆中如果原型對象中的成員變量是基本數據類型的話,將直接複製一份給新的克隆對象。 但是如果成員變量是引用數據類型的話, 是會將引用對象在內存中的地址複製一份給新的克隆對象。Object中clone()方法就是淺拷貝。 注意: 需要注意的是能夠實現克隆的Java類必須實現一個標識接口Cloneable,表示這個Java類支持被複制。如果一個類沒有實現這個接口但是調用了clone()方法,Java編譯器將拋出一個CloneNotSupportedException異常

深克隆

在深克隆中無論原型對象中的成員變量是基本數據類型還是引用數據類型。都將複製一份給新的克隆對象。在代碼中我們可以通過實現序列來完成深克隆(Serializable),---> 通過序列化實現的拷貝不僅可以複製對象本身,而且可以複製其引用的成員對象,因此通過序列化將對象寫到一個流中,再從流裏將其讀出來,可以實現深克隆。

在代碼中使用

在寫代碼中,碰到過要將一個對象傳遞給另一個對象, 這兩個對象是一個類的實例化。 之前我是通過先new出來一個新對象然後通過get()、set()。將舊對象的值複製給新的對象,如果用原型模式的話,可以省去很多set()、get()。使用Beanutils 作爲淺拷貝。使用Serializable序列化實現深拷貝。

10、簡單介紹一下工廠模式,並描述他們各自的優劣以及使用場景?

工廠模式(創建型模式)分爲3種:簡單工廠模式、工廠方法模式、抽象工廠模式。

簡單工廠模式:

優點:1、工廠類中包含了必要的判斷邏輯,可以決定在什麼時候創建哪一個產品類的對象。而客戶端可以不用管對象(實例)的創建。實現了對象的創建與使用的分離。2、客戶端不需要知道要使用的實例的具體類型,只需要知道具體的產品類對應的參數即可。

缺點:1、工廠類中有很多 創建實例的邏輯代碼,一旦不能正常工作,整個系統都會受到影響。2、使用簡單工廠模式肯定會出現很多工廠類,會增加系統的複雜度。

適用場景:工廠類負責創建的對象比較少,由於創建的對象較少,不會造成工廠方法中的業務邏輯太過複雜

工廠方法模式:

優點:1、基於工廠角色和產品角色的多態性設計是工廠方法模式的關鍵。它能夠讓工廠可以自主確定創建何種產品對象,而如何創建這個對象的細節則完全封裝在具體工廠內部。工廠方法模式之所以又被稱爲多態工廠模式,就正是因爲所有的具體工廠類都具有同一抽象父類。2、使用工廠方法模式的另一個優點是在系統中加入新產品時,無須修改抽象工廠和抽象產品提供的接口,無須修改客戶端,也無須修改其他的具體工廠和具體產品,而只要添加一個具體工廠和具體產品就可以了,這樣,系統的可擴展性也就變得非常好,完全符合“開閉原則”。

缺點:1、在添加新產品時,需要編寫新的具體產品類,而且還要提供與之對應的具體工廠類,系統中類的個數將成對增加,在一定程度上增加了系統的複雜度。

使用場景:客戶端不知道它所需要的對象的類。在工廠方法模式中,客戶端不需要知道具體產品類的類名,只需要知道所對應的工廠即可,具體的產品對象由具體工廠類創建,可將具體工廠類的類名存儲在配置文件或數據庫中。

抽象工廠模式:

抽象工廠模式與工廠方法模式最大的區別在於,工廠方法模式針對的是一個產品等級結構,而抽象工廠模式需要面對多個產品等級結構,一個工廠等級結構可以負責多個不同產品等級結構中的產品對象的創建。

優點:1、但由於工廠方法模式中的每個工廠只生產一類產品,可能會導致系統中存在大量的工廠類,勢必會增加系統的開銷。此時,我們可以考慮將一些相關的產品組成一個“產品族”,由同一個工廠來統一生產,這個就是抽象工廠模式的思想。

11、如何使用最精簡的語句描述產品等級結構和產品族?

產品等級結構產品等級結構即產品的繼承結構。 如一個抽象類是電視機,其子類有海爾電視機、海信電視機、TCL電視機,則抽象電視機與具體品牌的電視機之間構成了一個產品等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。

產品族:在抽象工廠中, 產品族是指由同一個工廠生產的,位於不同產品等級結構中的一組產品。如海爾電器工廠生產的海爾電視機、海爾電冰箱,海爾電視機位於電視機產品等級結構中,海爾電冰箱位於電冰箱產品等級結構中,海爾電視機、海爾電冰箱構成了一個產品族。

   (1) 增加產品族:對於增加新的產品族,抽象工廠模式很好地支持了“開閉原則”,只需要增加具體產品並對應增加一個新的具體工廠,對已有代碼無須做任何修改。
​
   (2) 增加新的產品等級結構:對於增加新的產品等級結構,需要修改所有的工廠角色,包括抽象工廠類,在所有的工廠類中都需要增加生產新產品的方法,違背了“開閉原則”。

12、實現代理模式的底層邏輯是什麼?

代理模式概念

給某一個對象提供一個代理或佔位符,並由代理對象來控制對原對象的訪問。 屬於結構型模式

代理模式:包含了 代理類、真實類。代理對象需要含有真實類的引用, 底層邏輯其實就是字節碼重組

靜態代理

寫一個增強類實現 被增強類實現的所有接口,需要把被增強類的引用獲取到

JDK動態代理

前提條件:

①必須知道要增強的接口

②必須用Proxy.newProxyInstance創建代理對象

③動態代理只能增強接口中定義的方法

動態代理實現原理: 用動態代理其實是重新生成了一個代理類, 這個代理類和原類 實現了同樣的接口。

CGLIB動態代理

CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法(繼承)

CGLib 動態代理執行代理方法效率之所以比 JDK 的高是因爲 Cglib 採用了 FastClass 機制,它的原理簡單來說就是:爲代理類和被代理類各生成一個 Class,這個 Class 會爲代理類或被代理類的方法分配一個 index(int 類)。這個 index 當做一個入參,FastClass就可以直接定位要調用的方法直接進行調用,這樣省去了反射調用,所以調用效率比 JDK動態代理通過反射調用高。

13、爲什麼JDK Proxy 要求目標類實現接口,而CGLIB對目標類無任何要求?

JDK Proxy

在JDK Proxy中生成的代理類需要繼承Proxy。獲取(繼承)含有InvocationHandler的構造方法,通過Proxy的InvocationHandler可以調用到invoke(), 這樣纔可以增強方法。在需要繼承proxy類獲得有關方法和InvocationHandler構造方法傳參的同時,java不能同時繼承兩個類,我們需要和想要代理的類建立聯繫,只能實現一個接口

CGLIB

CGLIb的實現原理是 生成一個代理類,且代理類繼承了被代理類(原類)。所以只要被代理類(原類)能被繼承,也就是沒有被final修飾。就可以生成代理類。

14、策略模式的本質是什麼? 多個策略可以組合使用嘛?如果可以該如何設計?

策略模式的來源:

在開發中實現一個功能有很多路徑,每個路徑對應着有一種算法。這時候可以使用一種設計模式來實現靈活的選擇解決路徑,也可以方便的添加新的路徑。這種模式稱之爲策略模式。

策略模式的的本質(目的):

策略模式主要是將算法的定義與算法的調用(使用)分開。 將算法專門定義在專門的策略類中,每一個策略類中封裝了一種算法實現。 使用的時候針對 抽象策略類編程, 符合“依賴倒轉原則”。在出現新的算法時,只需要增加一個新的實現了抽象策略類的具體策略類即可。 策略模式是一種 行爲型模式。

多個策略可以組合使用。如果是讓我來設計,1、我首先考慮用到裝飾者模式,因爲所有策略類都可以去繼承與抽象的策略類, 假如 策略A和策略B。 策略A想要使用到策略B的算法, 那麼只需要拿到策略B的引用,那麼就可以取組合策略B中的算法。 2、代理模式也可以搞定。3、適配器模式可以。 4、委派模式,可以通過委派類來對具體的策略類進行組合使用。

15、代理模式和裝飾器模式的區別和使用場景?

首先代理模式和裝飾器模式都屬於結構型模式。

區別: 代理模式主要分爲: 靜態代理和動態代理兩種, 其中靜態代理和裝飾者模式實現的機制是一樣的。 但是它們的目的(職責)是不一樣的。裝飾模式是 以對客戶端透明的方式擴展對象的功能,是繼承關係的一個替代方案, 它主要目的是 爲所裝飾的對象增強功能,裝飾模式重在裝飾,添加新的行爲,但是不論添加什麼都是方法所知道的,經過安檢才裝飾上的; 而代理模式是爲原對象生成了一個代理類。並且有代理對象控制了原對象的引用。 也就是說原對象的一切操作,交給了代理類。代理類全權負責了, 代理類控制了原對象,並不提供對象本身的增強功能。 代理模式重在控制。可以在方法調用前,調用後增加行爲,甚至徹底改變方法的行爲

使用場景: 裝飾者模式在源碼中的使用: 在 JDK 中體現最明顯的類就是 IO 相關的類,如BufferedReader、InputStream、OutputStream。一下情況可以使用裝飾者模式: (1) 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。(2)當不能採用繼承的方式對系統進行擴展或者採用繼承不利於系統擴展和維護時可以使用裝飾模式。不能採用繼承的情況主要有兩類:第一類是系統中存在大量獨立的擴展,爲支持每一種擴展或者擴展之間的組合將產生大量的子類,使得子類數目呈爆炸性增長;第二類是因爲類已定義爲不能被繼承(如Java語言中的final類) 代理模式: 1、當客戶端對象需要訪問遠程主機中的對象時可以使用 遠程代理。2、當需要控制對一個對象的訪問,爲不同用戶提供不同級別的訪問權限時可以使用保護代理。3、 當需要爲一個對象的訪問(引用)提供一些額外的操作時可以使用智能引用代理。

平時怎麼使用?

如果你寫了一個方法,後續考慮要給這個方法添加一些功能,可以選擇裝飾模式。

如果你要寫一堆方法,後續考慮統一給這些方法添加功能(比如日誌記錄,資源回收),可以選擇代理模式。

16、聊聊觀察者模式的設計思想。

觀察者模式用於建立一種對象與對象之間的依賴關係,一個對象發生改變時將自動通知其他對象,其他對象將相應作出反應。在觀察者模式中,發生改變的對象稱爲觀察目標,而被通知的對象稱爲觀察者,一個觀察目標可以對應多個觀察者,而且這些觀察者之間可以沒有任何相互聯繫,可以根據需要增加和刪除觀察者,使得系統更易於擴展。

觀察者模式也可以被稱爲發佈-訂閱模式。 一個對象狀態發生改變,其相關依賴的對象都可以得到通知,並且自動更新。

17、工作中了除了打架熟悉的MQ,還有哪些場景可以使用觀察者模式?

java中的Observable類(java.util)和Observer 接口 實現了觀察者模式。

Observer接口

在java.util.Observer接口中只聲明一個方法,它充當抽象觀察者,其方法聲明代碼如下所示:
​
void  update(Observable o, Object arg);

當觀察目標的狀態發生變化時,該方法將會被調用,在Observer的子類中將實現update()方法,即具體觀察者可以根據需要具有不同的更新行爲。當調用觀察目標類Observable的notifyObservers()方法時,將執行觀察者類中的update()方法。

Observable類

java.util.Observable類充當觀察目標類,在Observable中定義了一個向量Vector來存儲觀察者對象,

方法名 方法描述
Observable() 構造方法,實例化Vector向量。
addObserver(Observer o) 用於註冊新的觀察者對象到向量中。
deleteObserver (Observer o) 用於刪除向量中的某一個觀察者對象
notifyObservers()和notifyObservers(Object arg) 通知方法,用於在方法內部循環調用向量中每一個觀察者的update()方法。
deleteObservers() 用於清空向量,即刪除向量中所有觀察者對象。
setChanged() 該方法被調用後會設置一個boolean類型的內部標記變量changed的值爲true,表示觀察目標對象的狀態發生了變化。
clearChanged() 用於將changed變量的值設爲false,表示對象狀態不再發生改變或者已經通知了所有的觀察者對象,調用了它們的update()方法。
hasChanged() 用於測試對象狀態是否改變。
countObservers() 用於返回向量中觀察者的數量。

MVC(Model-View-Controller)架構中也應用了觀察者模式,MVC是一種架構模式,它包含三個角色:模型(Model),視圖(View)和控制器(Controller)。其中模型可對應於觀察者模式中的觀察目標,而視圖對應於觀察者,控制器可充當兩者之間的中介者。當模型層的數據發生改變時,視圖層將自動改變其顯示內容

18、什麼場景下才應該使用委派模式?

先說一下委派模式的概念。 委派模式是用來負責任務的調度和分配任務的。 還有就是委派模式不屬於23種設計模式。

委派模式有點像代理模式,又有點像策略模式。

舉個例子:公司老闆給項目經理下達任務,將任務全權交給項目經理,由項目經理根據一定的策略將任務分配給小組成員。 這其中老闆給項目經理下達任務,相當於把工作委派給了項目經理。由項目經理全權負責, 我們也可以說項目經理其實就是老闆的代理。(但是代理模式注重的是過程,二委派模式注重的是結果。)項目經理在給小組成員分配任務的時候,根據不同的人擅長的技術不一樣來分配任務。 這時候又特別像策略模式。

委派模式的核心就是分發、調度、派遣。也可以這麼說 委派模式就是靜態代理和策略模式一種特殊的組合

springmvc源碼中使用了委派模式。DispatcherServlet

19、爲什麼雙親委派一般使用繼承來實現?

我理解是使用繼承實現是根據加載的順序有關係。 因爲大家都知道雙親委派機制: 如果一個類加載器收到類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器完成。每個類加載器都是如此,只有當父加載器在自己的搜索範圍內找不到指定的類時(即ClassNotFoundException),子加載器纔會嘗試自己去加載。 因爲它每次加載都是先找父加載器的。 如果不使用繼承的話,比如使用接口實現,那麼可能會有很多接口。我們很難區分是哪個父接口是他的父加載器。 使用繼承,利用單繼承特性,我們就能直接找到父加載器,然後進行接下來的操作。

類加載器

  • 啓動類加載器(Bootstrap ClassLoader):由C++語言實現(針對HotSpot),負責將存放在<JAVA_HOME>\lib目錄或-Xbootclasspath參數指定的路徑中的類庫加載到內存中。

  • 其他類加載器:由Java語言實現,繼承自抽象類ClassLoader。如:

    • 擴展類加載器(Extension ClassLoader):負責加載<JAVA_HOME>\lib\ext目錄或java.ext.dirs系統變量指定的路徑中的所有類庫。

    • 應用程序類加載器(Application ClassLoader)。負責加載用戶類路徑(classpath)上的指定類庫,我們可以直接使用這個類加載器。一般情況,如果我們沒有自定義類加載器默認就是用這個加載器。

20、軟件設計階段可能應用適配器模式嗎? 如果用,在什麼場景下才應用?

適配器模式(Adapter模式)便是結構型中的其中一個模式,它的作用是:將一個類的接口轉換成客戶希望的另外一個接口。Adapter模式使原本由於接口不兼容而不能在一起工作的類可以一起工作。 適配器模式應用場景   (1)想要使用一個已經存在的類,但是它卻不符合現有的接口規範,導致無法直接去訪問,這時創建一個適配器就能間接去訪問這個類中的方法。   (2)我們有一個類,想將其設計爲可重用的類(可被多處訪問),我們可以創建適配器來將這個類來適配其他沒有提供合適接口的類。   以上兩個場景其實就是從兩個角度來描述一類問題,那就是要訪問的方法不在合適的接口裏,一個從接口出發(被訪問),一個從訪問出發(主動訪問)。 ​ 一般在軟件設計階段不會考慮適配器模式,而是在隨着軟件維護,由於不同產品不同廠家造成功能相同而接口不同的情況下的解決方案。

而在設計階段中,如果想要使用接口中的某個或某些方法,但是接口中有太多方法,我們要使用時必須實現接口並實現其中的所有方法,可以使用抽象類來實現接口,並不對方法進行實現(僅置空),然後我們再繼承這個抽象類來通過重寫想用的方法的方式來實現。這個抽象類就是適配器。這種場景下會使用到適配器模式。

21、模板方法模式如何與其他設計模式結合?

先說一下模板模式吧。 模板模式是一種基於繼承的代碼複用技術。是一種類行爲型模式。

一個模板方法是定義在抽象類中的、把基本操作方法組合在一起形成一個總算法或一個總行爲的方法。這個模板方法定義在抽象類中,並由子類不加以修改地完全繼承下來。模板方法是一個具體方法,它給出了一個頂層邏輯框架,而邏輯的組成步驟在抽象類中可以是具體方法,也可以是抽象方法。由於模板方法是具體方法,因此模板方法模式中的抽象層只能是抽象類,而不是接口

模板方法模式中,在父類中提供了一個定義算法框架的模板方法,還提供了一系列抽象方法、具體方法和鉤子方法,其中鉤子方法的引入使得子類可以控制父類的行爲

1、模板方法模式可以和策略模式結合起來使用,具體的模板方法類,實現了抽象類之後,可以引入策略模式,根據不同的業務需求,選擇最好的算法來解決問題

2、模板方法模式可以和裝飾者模式結合, 因爲兩種模式都是基於繼承的,所以在模板方法中可以使用裝飾者模式來增加某個具體的模板方法。

22、責任鏈模式能解決什麼問題?如何解決?

責任鏈模式(Chain of Responsibility)

定義: 避免發送者和接受者耦合在一起, 讓多個對象都有可能接收請求,讓這些對象連接成一條鏈, 並且讓這條鏈傳遞請求, 知道有對象處理請求爲止。 是一種行爲型模式。

職責鏈模式並不創建職責鏈,職責鏈的創建工作必須由系統的其他部分來完成,一般是在使用該職責鏈的客戶端中創建職責鏈

責任鏈模式中,一個處理者只有兩種選擇: 1、承擔全部責任, 2、將責任推給下家。

使用場景: 在Web應用開發中創建一個過濾器(Filter)鏈來對請求數據進行過濾,在工作流系統中實現公文的分級審批等等,使用職責鏈模式可以較好地解決此類問題。 如果我們遇到這種需求: 有多個對象可以處理同一個請求,具體哪個對象處理該請求待運行時刻再確定,客戶端只需將請求提交到鏈上,而無須關心請求的處理對象是誰以及它是如何處理的。 我們就可以使用責任鏈模式。

責任鏈解決問題的優勢:

1、請求處理對象僅需維持一個指向其後繼者的引用,而不需要維持它對所有的候選處理者的引用,可簡化對象的相互連接。2、在給對象分派職責時,職責鏈可以給我們更多的靈活性,可以通過在運行時對該鏈進行動態的增加或修改來增加或改變處理一個請求的職責。3、 在系統中增加一個新的具體請求處理者時無須修改原有系統的代碼,只需要在客戶端重新建鏈即可,從這一點來看是符合“開閉原則”的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章