你當前所在位置:首頁 > IT技術探討 > Java軟件開發常用的設計模式匯總

Java軟件開發常用的設計模式匯總

單例模式

 

簡單點說,就是一個應用程序中,某個類的實例對象只有一個,你沒有辦法去new,因為構造器是被private修飾的,一般通過getInstance()的方法來獲取它們的實例。

 

getInstance()的返回值是一個對象的引用,并不是一個新的實例,所以不要錯誤的理解成多個對象。單例模式實現起來也很容易,直接看demo吧:

 

Java軟件開發設計模式-單例模式

 

上面的是最基本的寫法,也叫懶漢寫法(線程不安全),下面再公布五種單例模式的寫法:

 

1、懶漢式寫法(線程安全)

 

Java軟件開發設計模式-單例模式懶漢寫法

 

2、餓漢式寫法

 

Java軟件開發設計模式-單例模式餓漢式寫法

 

3、靜態內部類

 

Java軟件開發設計模式-單例模式靜態內部類寫法

 

4、枚舉

 

Java軟件開發設計模式-枚舉寫法

 

這種方式是Effective Java作者Josh Bloch 提倡的方式,它不僅能避免多線程同步問題,而且還能防止反序列化重新創建新的對象,可謂是很堅強的壁壘啊,不過,個人認為由于1.5中才加入enum特性,用這種方式寫不免讓人感覺生疏。

 

5、雙重校驗鎖

 

Java軟件開發設計模式-單例模式雙重校驗鎖寫法

 

總結:我個人比較喜歡靜態內部類寫法和餓漢式寫法,其實這兩種寫法能夠應付絕大多數情況了。其他寫法也可以選擇,主要還是看業務需求吧。

 

觀察者模式

 

對象間一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并被自動更新。

 

Java軟件開發設計模式-觀察者模式

觀察者模式UML圖

 

看不懂圖的人端著小板凳到這里來,給你舉個栗子:假設有三個人,小美(女,22),小王和小李。小美很漂亮,小王和小李是兩個程序猿,時刻關注著小美的一舉一動。有一天,小美說了一句:“誰來陪我打游戲啊。”這句話被小王和小李聽到了,結果樂壞了,蹭蹭蹭,沒一會兒,小王就沖到小美家門口了,在這里,小美是被觀察者,小王和小李是觀察者,被觀察者發出一條信息,然后觀察者們進行相應的處理,看代碼:

 

Java軟件開發設計模式-觀察者模式

 

這個接口相當于小王和小李的電話號碼,小美發送通知的時候就會撥打getMessage這個電話,撥打電話就是調用接口,看不懂沒關系,先往下看

 

Java軟件開發設計模式-觀察者模式

 

代碼很簡單,我們再看看小美的代碼:

 

Java軟件開發設計模式-觀察者模式

 

我們寫一個測試類來看一下結果對不對

 

Java軟件開發設計模式-觀察者模式

 

完美~

 

裝飾者模式

 

對已有的業務邏輯進一步的封裝,使其增加額外的功能,如Java中的IO流就使用了裝飾者模式,用戶在使用的時候,可以任意組裝,達到自己想要的效果。 舉個栗子,我想吃三明治,首先我需要一根大大的香腸,我喜歡吃奶油,在香腸上面加一點奶油,再放一點蔬菜,最后再用兩片面包夾一下,很豐盛的一頓午飯,營養又健康。(ps:不知道上海哪里有賣好吃的三明治的,求推薦~)那我們應該怎么來寫代碼呢? 首先,我們需要寫一個Food類,讓其他所有食物都來繼承這個類,看代碼:

 

Java軟件開發設計模式-裝飾者模式

 

代碼很簡單,我就不解釋了,然后我們寫幾個子類繼承它:

 

Java軟件開發設計模式-裝飾者模式

Java軟件開發設計模式-裝飾者模式


這幾個類都是差不多的,構造方法傳入一個Food類型的參數,然后在make方法中加入一些自己的邏輯,如果你還是看不懂為什么這么寫,不急,你看看我的Test類是怎么寫的,一看你就明白了

 

Java軟件開發設計模式-裝飾者模式

 

看到沒有,一層一層封裝,我們從里往外看:最里面我new了一個香腸,在香腸的外面我包裹了一層奶油,在奶油的外面我又加了一層蔬菜,最外面我放的是面包,是不是很形象,哈哈~ 這個設計模式簡直跟現實生活中一摸一樣,看懂了嗎? 我們看看運行結果吧

 

Java軟件開發設計模式-裝飾者模式運行結果

運行結果

 

一個三明治就做好了~

 

適配器模式

 

將兩種完全不同的事物聯系到一起,就像現實生活中的變壓器。假設一個手機充電器需要的電壓是20V,但是正常的電壓是220V,這時候就需要一個變壓器,將220V的電壓轉換成20V的電壓,這樣,變壓器就將20V的電壓和手機聯系起來了。

 

Java軟件開發設計模式-適配器模式


Java軟件開發設計模式-適配器模式

 

工廠模式

 

1、簡單工廠模式:一個抽象的接口,多個抽象接口的實現類,一個工廠類,用來實例化抽象的接口

 

Java軟件開發設計模式-工廠模式-簡單工廠模式

Java軟件開發設計模式-工廠模式-簡單工廠模式

 

2、工廠方法模式:有四個角色,抽象工廠模式,具體工廠模式,抽象產品模式,具體產品模式。不再是由一個工廠類去實例化具體的產品,而是由抽象工廠的子類去實例化產品

 

Java軟件開發設計模式-工廠模式-工廠方法模式

Java軟件開發設計模式-工廠模式-工廠方法模式

 

3、抽象工廠模式:與工廠方法模式不同的是,工廠方法模式中的工廠只生產單一的產品,而抽象工廠模式中的工廠生產多個產品

 

Java軟件開發設計模式-工廠模式-抽象工廠模式

 

代理模式(proxy)

 

簡單說即是在不改變源碼的情況下,實現對目標對象的功能擴展。比如有個歌手對象叫Singer,這個對象有一個唱歌方法叫sing()。

 

Java軟件開發設計模式-代理模式

 

假如你希望,通過你的某種方式生產出來的歌手對象,在唱歌前后還要想觀眾問好和答謝,也即對目標對象Singer的sing方法進行功能擴展。

 

Java軟件開發設計模式-代理模式

 

但是往往你又不能直接對源代碼進行修改,可能是你希望原來的對象還保持原來的樣子,又或許你提供的只是一個可插拔的插件,甚至你有可能都不知道你要對哪個目標對象進行擴展。這時就需要用到java的代理模式了。網上好多用生活中的經理人的例子來解釋“代理”,看似通俗易懂,但我覺得不適合程序員去理解。程序員應該從代碼的本質入手。

 

想要實現以上的需求有三種方式:

 

1、靜態代理

 

Java軟件開發設計模式-代理模式-靜態代理

 

測試

 

Java軟件開發設計模式-代理模式-靜態代理測試

 

總結:其實這里做的事情無非就是,創建一個代理類SingerProxy,繼承了ISinger接口并實現了其中的方法。只不過這種實現特意包含了目標對象的方法,正是這種特征使得看起來像是“擴展”了目標對象的方法。假使代理對象中只是簡單地對sing方法做了另一種實現而沒有包含目標對象的方法,也就不能算作代理模式了。所以這里的包含是關鍵。

 

缺點:這種實現方式很直觀也很簡單,但其缺點是代理對象必須提前寫出,如果接口層發生了變化,代理對象的代碼也要進行維護。如果能在運行時動態地寫出代理對象,不但減少了一大批代理類的代碼,也少了不斷維護的煩惱,不過運行時的效率必定受到影響。這種方式就是接下來的動態代理。

 

2、動態代理(也叫JDK代理)

 

 跟靜態代理的前提一樣,依然是對Singer對象進行擴展。

 

Java軟件開發設計模式-代理模式-動態代理

 

這回直接上測試,由于java底層封裝了實現細節,所以代碼非常簡單,格式也基本上固定。

 

調用Proxy類的靜態方法newProxyInstance即可,該方法會返回代理類對象。

 

Java軟件開發設計模式-代理模式-動態代理

 

接收的三個參數依次為:

 

● ClassLoader loader:指定當前目標對象使用類加載器,寫法固定

● Class

● InvocationHandler h:事件處理接口,需傳入一個實現類,一般直接使用匿名內部類

 

測試代碼

 

Java軟件開發設計模式-代理模式-動態代理測試代碼

 

總結:以上代碼只有標黃的部分是需要自己寫出,其余部分全都是固定代碼。由于java封裝了newProxyInstance這個方法的實現細節,所以使用起來才能這么方便。

 

缺點:可以看出靜態代理和JDK代理有一個共同的缺點,就是目標對象必須實現一個或多個接口,加入沒有,則可以使用Cglib代理。

 

3、Cglib代理

 

前提條件:

 

● 需要引入cglib的jar文件,由于Spring的核心包中已經包括了Cglib功能,所以也可以直接引入spring-core-3.2.5.jar

● 目標類不能為final

● 目標對象的方法如果為final/static,那么就不會被攔截,即不會執行目標對象額外的業務方法

 

Java軟件開發設計模式-代理模式-Cglib代理


Java軟件開發設計模式-代理模式-Cglib代理

 

這里的代碼也非常固定,只有標黃部分是需要自己寫出

 

測試

 

Java軟件開發設計模式-代理模式-Cglib代理測試代碼

 

總結:三種代理模式各有優缺點和相應的適用范圍,主要看目標對象是否實現了接口。以Spring框架所選擇的代理模式舉例

 

Java軟件開發設計模式-代理模式舉例


課程預約

极速1分彩_Welcome