JAVA常用的七种设计模式
學(xué)習(xí)設(shè)計(jì)模式之前,我們先要了解一下設(shè)計(jì)模式的怎么來(lái)的?
對(duì)于設(shè)計(jì)人員,特別是開發(fā)人員嗎,往往受限于眼界或經(jīng)驗(yàn)不能夠體會(huì)到設(shè)計(jì)原則的實(shí)用性,或者在處理具體問(wèn)題時(shí),不知道如何把設(shè)計(jì)原則應(yīng)用到到設(shè)計(jì)和代碼,因此產(chǎn)生了“模式”。
隨著參與的項(xiàng)目越來(lái)越多,人們發(fā)現(xiàn):很多問(wèn)題并不是一個(gè)項(xiàng)目中出現(xiàn)的,它會(huì)在很多的項(xiàng)目中出現(xiàn)。于是人們就把這些問(wèn)題總結(jié)出來(lái),然后給出了解決這些問(wèn)題的方案,而這些方案–“模式”(解決問(wèn)題的套路)。
設(shè)計(jì)模式的分類
1.創(chuàng)建模式:創(chuàng)建一些特殊的對(duì)象,或者在特殊要求下創(chuàng)建對(duì)象。
2.結(jié)構(gòu)模式:主要利用組合/聚合或者繼承,讓類與類能夠形成某種關(guān)聯(lián)關(guān)系 – 代理。
3.行為模式:刻畫了類和對(duì)象交換及分配職責(zé)的方式。
接下來(lái)我們正式介紹七種常用的設(shè)計(jì)模式
單例模式
1.餓漢模式(最基本的單例模式)
類加載時(shí),會(huì)直接實(shí)例化單例對(duì)象,以后都返回該對(duì)象的引用。
- 缺點(diǎn):類加載時(shí),會(huì)直接實(shí)例化單例對(duì)象,不管是否使用到該單例對(duì)象,浪費(fèi)內(nèi)存。
- 優(yōu)點(diǎn):沒(méi)有枷鎖,執(zhí)行效率高,線程安全的實(shí)例。
2.懶漢模式(線程不安全、線程安全但效率低)
不要直接在類加載時(shí)實(shí)例化,而是在調(diào)用方法時(shí),再實(shí)例化。
- 優(yōu)點(diǎn):不會(huì)占用內(nèi)存
- 缺點(diǎn):安全方面 單線程情況下,是安全的,但是在多線程下,多個(gè)線程可能同時(shí)執(zhí)行singleton == null 都為true,會(huì)創(chuàng)建多個(gè)實(shí)例在內(nèi)存中。
2.1懶漢模式(雙重檢驗(yàn)?zāi)J?線程安全,且效率高的) 把鎖的粒度變小,只鎖第一次初始化時(shí))
- 實(shí)例會(huì)在調(diào)用getInstance方法時(shí)創(chuàng)建,僅在第一調(diào)用初始化時(shí)需要鎖住。
3.內(nèi)部類實(shí)現(xiàn)模式
通過(guò)靜態(tài)內(nèi)部類,完成單例模式的創(chuàng)建。
- 在外部類加載時(shí),并不會(huì)加載內(nèi)部類,也就是不會(huì)執(zhí)行new 實(shí)例(),這屬于懶加載。
- 只有第一次調(diào)用getInstance方法時(shí),才會(huì)加載。
4.枚舉實(shí)現(xiàn)
通過(guò)枚舉創(chuàng)建 單例模式。
- 實(shí)現(xiàn)單例的最佳方法。簡(jiǎn)潔,支持自動(dòng)序列化機(jī)制,防止多次實(shí)例化,但目前還沒(méi)有被廣泛采用。
工廠模式
講使用者和對(duì)象的生產(chǎn)者進(jìn)行分離。
在工廠模式中,幾乎都有三種角色,工廠(抽象工廠、具體工廠) 產(chǎn)品(抽象產(chǎn)品、具體產(chǎn)品) 使用者。使用者想要使用產(chǎn)品,不用自己去生產(chǎn)產(chǎn)品,把生產(chǎn)的動(dòng)作交給工廠去做,使用者只需要從工廠提供產(chǎn)品的位置(方法)去拿就好。
-
1.簡(jiǎn)單工廠模式–顧客需要給出清單。
變化點(diǎn)在產(chǎn)品對(duì)象上,所以我們會(huì)抽象產(chǎn)品,然后通過(guò)一個(gè)工廠,根據(jù)不同的情況產(chǎn)生不同的產(chǎn)品對(duì)象。 -
2.工廠方法模式–根據(jù)工廠能產(chǎn)生什么顧客拿什么。
工廠可以產(chǎn)生統(tǒng)一品牌的商品,會(huì)根據(jù)商品去抽象工廠,對(duì)每一個(gè)產(chǎn)品,提供一個(gè)工廠實(shí)現(xiàn)類。 -
3.抽象工廠模式–根據(jù)工廠能產(chǎn)生什么顧客拿什么,但是工廠能產(chǎn)生的產(chǎn)品會(huì)有多種品牌。
超級(jí)工廠,可以生產(chǎn)不同品牌的各種產(chǎn)品,抽象出超級(jí)工廠,也要抽象出產(chǎn)品,然后根據(jù)不同的品牌給出該品牌商品的工工廠實(shí)現(xiàn)類。
原型模式
根據(jù)一個(gè)已經(jīng)存在的對(duì)象,創(chuàng)建一個(gè)和他一樣的對(duì)象。-- 克隆
淺克隆-- 利用Object中clone()實(shí)現(xiàn)
1.讓被克隆的類實(shí)現(xiàn)Cloneable接口。
2.重寫clone方法,方法訪問(wèn)修飾符public。
3.對(duì)象.clone()的方式的到一個(gè)一樣的對(duì)象。
淺克隆指,被克隆的對(duì)象會(huì)產(chǎn)生一個(gè)新的,但是對(duì)象屬性不會(huì)產(chǎn)生。
public class Man implements Cloneable {private String name;public Car car = new Car();public Man clone() throws CloneNotSupportedException{Object obj = super.clone();return (Man)obj;}}深度克隆
1.克隆對(duì)象所涉及的自定義類,需要實(shí)現(xiàn)序列化接口。
2.在需要克隆的類中,添加一個(gè)方法,完成序列化反序列化即可。
public class Man implements Cloneable,Serializable {private String name;public Car car = new Car();public Man depthClone() throws IOException, ClassNotFoundException {//獲取對(duì)象信息,把當(dāng)前對(duì)象寫入另一塊內(nèi)存ByteArrayOutputStream bo = new ByteArrayOutputStream();ObjectOutputStream objOut = new ObjectOutputStream(bo);objOut.writeObject(this);//讀取內(nèi)存 創(chuàng)建對(duì)象ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());ObjectInputStream objIn = new ObjectInputStream(bi);Object obj = objIn.readObject();return (Man) obj;}}代理模式
1.靜態(tài)代理
根據(jù)目標(biāo)對(duì)象需要代理的行為,抽象出一個(gè)接口(包含了需要代理的行為),目標(biāo)類和代理類都需要去實(shí)現(xiàn)該接口,然后將目標(biāo)對(duì)象注入到代理類中,此時(shí)就可以在代理類中調(diào)用目標(biāo)對(duì)象的行為,并為止附加非功能性邏輯。
2.動(dòng)態(tài)代理之JDK代理
-
第一步,實(shí)現(xiàn)接口InvocationHandler,然后重寫invoke方法,在invoke方法中調(diào)用目標(biāo)對(duì)的方法。
-
第二步,提供一個(gè)自定義的方法,通過(guò)Proxy.newProxyInstance()得到代理對(duì)象。
3.動(dòng)態(tài)代理之Cglib代理
-
第一步,導(dǎo)入Cglib依賴(包)。
-
第二步,實(shí)現(xiàn)接口MethodInterceptor,重寫intercept方法,在其中完成目標(biāo)對(duì)象的方法調(diào)用。
-
第三步,提供自定義方法,通過(guò)工具類獲取得到代理對(duì)象。
裝飾器模式
對(duì)象功能的擴(kuò)展能夠根據(jù)需要來(lái)動(dòng)態(tài)地實(shí)現(xiàn)。
以咖啡舉例:
-
1.根據(jù)對(duì)象抽象一個(gè)公共的接口。
-
2.根據(jù)接口給出不同的實(shí)現(xiàn)類(主料類(主料類產(chǎn)生的對(duì)象就是被裝飾的對(duì)象) 和 配料類–裝飾類)。
-
3.在配料類中注入被裝飾的對(duì)象。
-
4.生產(chǎn)咖啡時(shí),先生產(chǎn)主料(被修飾的對(duì)象),然后用配料不斷去修飾主料。
適配器模式
使得原本不兼容的兩個(gè)接口(功能)可以兼容 – 搭建了兩個(gè)接口間的橋梁。
class Tel{public void call(){}}class Carame{public void make(){}}class Phone extends Tel{private Carame c = new Carame();public void make(){c.make();}}實(shí)現(xiàn)適配器的方案,繼承或者依賴(推薦使用)
優(yōu)點(diǎn):
-
可以讓沒(méi)有任何關(guān)聯(lián)的類,一起運(yùn)行;
-
提高了類的復(fù)用
-
靈活性好
缺點(diǎn):
-
過(guò)多的使用適配器,會(huì)導(dǎo)致系統(tǒng)非常混亂,不容具體把控
-
java是單繼承。
觀察者模式
- 主題類(由它產(chǎn)生的對(duì)象 就是 被觀察的對(duì)象) 繼承 Observable的類。
在主題類,需要針對(duì)主題(價(jià)格的變化進(jìn)行關(guān)注,設(shè)置變化點(diǎn),然后通知觀察者價(jià)格有了變化)。
- 觀察者類(由它產(chǎn)生的對(duì)象 就是 觀察者) 實(shí)現(xiàn)Observer接口。
重寫update(當(dāng)主題發(fā)生變化時(shí),會(huì)調(diào)用方法)。
- 首先產(chǎn)生主題對(duì)象(被觀察對(duì)象),產(chǎn)生觀察者對(duì)象,然后給主題對(duì)象設(shè)置觀察者,最后通過(guò)更改主題的值,測(cè)試觀察者是否有觀測(cè)到主題值的改變。
總結(jié)
以上是生活随笔為你收集整理的JAVA常用的七种设计模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 计算机类公务员如何提升自己,大学毕业才发
- 下一篇: java常用设计模式总结