雖然你覺得大炮肯定是個標題黨,但你終究還是點進來了(別打我,手動狗頭保命),畢竟這性價比也太高了,4分鐘10種,如果是真的就賺大發了,

但是大炮可以肯定的告訴你,只要正兒八經的參與過幾個專案,有個一兩年的開發經驗,你肯定已經用過并且可能已經理解了一些設計模式了,只是并不自知而已,今天大炮就來給你好好縷一縷,
單例、工廠模式
這兩個設計模式大家都不陌生,很多讀者也都已經自學過了,比如餓漢、懶漢單例模式,簡單、抽象工廠模式,而且這兩個模式,就像兄弟一樣,經常結對出現,所以大炮放到一起來講,我們先來看一行代碼:
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
非常眼熟吧,這是我們平時用來獲取日志物件的一段代碼,但是重點并不是這個 logger 而是 LoggerFactory,顧名思義用來專門用來造 logger 的工廠 ,是一個工廠模式很好的體現,同時作為工廠呢,它又是單例的,畢竟new一個工廠就夠了嘛,自己實體化那么多個干嘛呢,單例杜絕了反復創建和銷毀物件的開銷,
同時它又用到了門面模式,這行代碼是不是很牛,用到了三個設計模式,我們接著往下看,
門面模式
在《阿里巴巴Java開發手冊》中,關于日志章節中專門有提到:
【強制】應用中不可直接使用日志系統(Log4j、Logback)中的 API,而應依賴使用日志框架 SLF4J 中的 API,使用門面模式的日志框架,有利于維護和各個類的日志處理方式統一,
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Abc.class);
有點感覺沒,門面模式其實就是把自己作為一個介面,自己并不提供真正的實作,什么,還是沒到位?那我們看看下面這段代碼:

是不是又很眼熟了,下單要干挺多事情,保存訂單,保存訂單項,減庫存...或者還有其他業務,如果所有這些方法的實作都放到 createOrder 這個方法里面,那代碼肯定是又長又臭,洋洋灑灑就奔著幾百上千行去了,所以有經驗的你們肯定會抽到好幾個子方法里面,就像上面一樣,然后挨個呼叫下就行了,(PS,真正的下單代碼肯定不是這么玩的,高并發下肯定掛了,看個意思就好)
沒錯,這也是門面模式,createOrder 方法并沒有給出具體的實作,直接呼叫了幾個子方法而已,可能有些讀者心里已經發出了嘲諷:就這?就這?這也算設計模式?我自己都會寫啦,

沒錯,就這~設計模式就是對經驗的總結,然后提出了一些建議和規范,其實并不是多么高深的東西,現在想想,如果給優秀的我們早生幾年,有些設計模式的創造者還指不定是誰呢,回到上面的代碼,雖然沒多少技術含量,但對呼叫者而言,我管你怎么實作,我輕輕調一下 createOrder 方法就完事了,這正是門面模式的精髓所在,
嗯,一行代碼 get 到了三個設計模式,咱們繼續,
代理模式
代理模式,是一個非常重要的設計模式,不理解它可能會讓你直接無緣大廠,大家一定要學會并理解這個東西,我們先來看一段代碼:

How old are you ? 怎么老是你 ? 沒錯,還是上面的圖,這次的關注點大家放在 @Transaction 上,注解本身沒啥用,只是作為一個標記,有時候會攜帶一些配置資訊,老開發已經知道我要講啥了,這里用到了Spring 中一個非常的重要特性:AOP編程,而AOP的實作原理就是代理模式,
代理模式的作用就是職責(或者說功能)增強,那Spring幫我們做了哪些增強呢?上圖的部分其實只有CRUD的業務代碼,事務方面一行都沒有,而沒Spring之前,我們是要這樣寫的:
try {
//加載驅動
Class.forName("com.mysql.jdbc.Driver");
//建立連接
Connection con = DriverManager.getConnection()
//開啟事務
con.setAutoCommit(true/false);
//真正的、我們每天都要寫的:)
C R U D
//提交事務
con.commit()
} catch (Exception e){
//失敗了還要自己手動回滾
con.rollback();
} finally {
//關閉連接
conn.close();
}
寫的偽代碼,不用在意細節,重要的是如果每個需要用到事務的方法都要這么重復寫,我們估計早瘋了,這里Spring就將這些重復的代碼使用動態代理給我們抽到代理類中去了,所以我們只用關注CRUD就成——從這個角度看,一定程度上造成了程式員的懶惰,不是我們不學習,只怪Spring太好用,
代理模式就不繼續發散了,后面會精講,
橋接模式
讓我猜猜看,是不是有些同學第一次聽到這個模式?猜對了待會下面給我留言點贊統計喔,但其實,我們每天都在用,咱們來看一段代碼:
//加載驅動
Class.forName("com.mysql.jdbc.Driver");
//建立連接
Connection con = DriverManager.getConnection()
沒錯,大炮又套娃了,用的就是上面的連接資料庫的代碼,大家每天都要連接資料庫的吧,
先鋪墊一個知識:Java 沒有真正能操作資料庫的方法,只是提供了一些抽象的介面,真正的實作在各個資料庫廠商提供的相應jar包內,mysql就由mysql的開發者提供,oracle的就由oracle的提供,
為什么我們這個DriverManager能直接get到Connection呢,就是使用了橋接模式,關鍵就在于這個Class.forName("com.mysql.jdbc.Driver"),Class.forName 只是加載了一個類而已,怎么做到的呢,我們來看這個Driver類到底干啥了:

其實就是一個靜態塊里面呼叫了java.sql.DriverManager 的 registeDriver方法,然后把mysql 的Driver物件傳了過去,起到了一個搭橋的作用,
多的就不擴展了,橋接模式的作用就是連接了一個抽象維度和一個實作維度,這里的抽象維度就是指 java,實作維度就是指 mysql,其實也可以說橋接的精髓在于“約定”,java 和 各資料庫廠商約定:你們底層實作我不管,但是你們得按照我的規矩來,呼叫我DriverManager的registerDriver方法才行,
中介者模式
聊完橋接模式,不得不聊下中介者模式了,橋接是關注兩個維度的連接,而中介者是關注多個多個維度,作用是統一管理多個多個維度的網狀資源,沒錯,可能你已經想到了,我們天天都在用的注冊中心就是一個中介者,比如 eureka、zookeeper,

如圖,所有的 service 都只和 Service Registry 耦合,而不是直接去依賴其他service ,中介者完美地解決了網狀依賴的復雜關系帶來的代碼混亂,總體來說中介者還是個比較容易理解的設計模式,這里就不做太多展開了,
解釋器模式
解釋器模式是個非常簡單的模式,有種自娛自樂的味道,如果你知道它是怎么自娛自樂的,那你也能跟著“娛樂一下”,來看一個熟悉的東東:
#每隔五秒執行一次
times = */5 * * * * ?
你的組態檔是不是也有corn運算式呢,這就是一個解釋器模式的體現,可能現在你的內心又:

解釋器模式定義了一種運算式(或者說是語言),并且也提供了決議運算式(語言)的方法,類似的還有正則運算式,Spring中的ExpressionParser也用到了解釋器模式,有興趣的同學可以去看看原始碼,
策略模式
策略模式也比較容易理解,大家在開發和日常生活中也經常用到,也是一個需要重點掌握的設計模式,每天買東西,使用手機支付,就是策略模式的一種體現,策略模式只注重結果,不管使用哪種策略(策略模式要求策略的數量是有限的),最后的結果都是一樣的,比如手機支付,不管使用哪種支付方式,該付多少還是得付多少,

原型模式
原型模式也是一種非常簡單,唉,凌晨一點多了,明天繼續寫吧,困了困了,

誒大炮又復活了,原型模式也是一種非常簡單的設計模式:給定一個物件實體,通過拷貝的技術創建新的物件,達到物件復用的效果,來看一段代碼:
UserVo userVO = new UserVO();
User user = mapper.selectByPrimaryKey(id);
if(user == null){
throw new Exception("未獲取到指定用戶");
}
/* 拷貝資料,傳給前端大佬渲染頁面 */
BeanUtils.copyProperties(user,userVO);
return userVO;
是不是非常眼熟了,可能有些讀者內心紛紛表示“是我本人沒錯了”,這里的BeanUtils.copyProperties 方法就用到了原型模式里面的 淺拷貝,
稍微提一句,不要使用Apache的 BeanUtils 來copy,性能問題比較嚴重,在《阿里巴巴Java開發手冊》中也有專門提到,如果需要切到Spring的copy方法,也有個坑需要注意下,這兩家的提供的copy,類名相同、方法名也相同,但引數的位置相反,切換時請多加注意并做好測驗,
迭代器模式
迭代器模式大家也天天都在用,直接上代碼:

這是一段生成簽名時,拼接引數的演算法,里面的 Iterator 就是迭代器模式的體現,給集合提供了一個全域訪問點,通過hasNext()判斷沒有下一個節點,next()方法獲取下個節點,直到所有節點都被訪問過,我們常用的 HashMap ,ArrayList 頂層都是 Collection,而 Collection又繼承了 Iterator 介面,來張ArrayList 的類圖感受下:

小結
大炮稍微給大家縷了一遍,有些同學是不是覺得自己又行了,原來不知不覺間,自己竟然用了這么多設計模式,卻不自知,其實還有很多,比如:
- 責任鏈模式,Spring security、Shiro這些權限框架都有用到,
- 觀察者模式,Spring 的 ContextLoaderListener 就有用到,
- 模板模式,Spring 中的 JdbcTemplate 有用到,
設計模式無處不在,平時開發我們也無時無刻在享受著設計模式帶來的好處,只是有些同學缺乏一個系統的認知,由于篇幅原因就不再過多介紹了,

好吧,標題黨不算太過分,超了三分鐘嘻嘻,
下期預告
今天講的還是比較片面和粗獷的,很多細節都沒有體現出來,這一期相當于是個設計模式的面試嘗鮮版,下一期會對設計模式做一個正式的介紹:
- 為什么要用設計模式
- 設計模式是什么
- 設計模式有哪些
- 設計模式的分類
大概就是上面這些了,然后就開始做具體某個模式的詳細分析和代碼實作(想先看什么模式記得私信我喔),
今天就先到這了,下次去面試被問到用過哪些設計模式,心里是不是就有底了,直接給他一頓連招13種統統安排上,我們下期見,
往期推薦
-
蔡大炮準備正式開張了
-
家雄又寫bug了

微信搜索 java-caidapao ,關注大炮~回復“面試題”,領取2020最新面試題
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/55048.html
標籤:Java
上一篇:PTA程式報錯:運行超時
下一篇:麻煩幫下忙

