一.設計模式的思維導向圖
二. 首先科普一下設計模式的七大原則:
設計模式(面向對象)有七大原則,分別是:
1.開放-封閉原則
通俗:對擴展開發,對修改關閉
2.單一職責原則
通俗:一個類只做一件事
3.依賴倒轉原則
通俗:類似IOC,采用接口編程
4.迪米特法則(也稱為最小知識原則)
通俗:高內聚,低耦合
5.接口隔離原則
通俗:細節接口
6.合成/聚合復用原則
通俗:避免使用繼承
7.里氏代換原則
通俗:子類不能去修改父類的功能
三、結構性模式:
1、適配器模式:
常用於將一個新接口適配舊接口
PS:在我們業務代碼中經常有新舊接口適配需求,可以采用該模式。
2、橋接模式:
將抽象和抽象的具體實現進行解耦,這樣可以使得抽象和抽象的具體實現可以獨立進行變化。
PS:這個模式,其實我們每天都在用到,但是你可能卻渾然不知。只要你用到面向接口編程,其實都是在用橋接模式。
3、組合模式
讓客戶端看起來在處理單個對象和對象的組合是平等的,換句話說,某個類型的方法同時也接受自身類型作為參數。(So in other words methods on a type accepting the same type)
PS:從上面那句英文我們就可以得知,組合模式常用於遞歸操作的優化上,比如每個公司都有個boss系統,都會有什么菜單的功能。比如一級菜單下有二級菜單,二級菜單又有三級菜單。刪除一級菜單的時候需要不斷刪除子菜單,那么這個設計模式你可以試試。總之,凡是有級聯操作的,你都可以嘗試這個設計模式。
4、裝飾者模式
動態的給一個對象附加額外的功能,因此它也是子類化的一種替代方法。該設計模式在JDK中廣泛運用,以下只是列舉一小部分
PS:這個模式使用就太廣了,我們常用的AOP,既有動態代理,也有裝飾者的味道。
5、門面模式
為一組組件,接口,抽象或子系統提供簡化的接口。
PS:我們每天使用的SLFJ日志就是門面日志,比如我們使用Dubbo,向外提供的服務就盡量采用門面模式,然后服務在調用各種service做聚合。
SLF4J,即簡單日志門面(Simple Logging Facade for Java),不是具體的日志解決方案,它只服務於各種各樣的日志系統。按照官方的說法,SLF4J是一個用於日志系統的簡單Facade,允許最終用戶在部署其應用時使用其所希望的日志System.
實際上,SLF4J所提供的核心API是一些接口以及一個LoggerFactory的工廠類。從某種程度上,SLF4J有點類似JDBC,不過比JDBC更簡單,在JDBC中,你需要指定驅動程序,而在使用SLF4J的時候,不需要在代碼中或配置文件中指定你打算使用那個具體的日志系統。如同使用JDBC基本不用考慮具體數據庫一樣,SLF4J提供了統一的記錄日志的接口,只要按照其提供的方法記錄即可,最終日志的格式、記錄級別、輸出方式等通過具體日志系統的配置來實現,因此可以在應用中靈活切換日志系統。
6、享元模式
使用緩存來減少對小對象的訪問時間
PS:只要用到了緩存,基本都是在使用享元模式。很多同學都說自己的項目太low了,都沒有用到什么設計模式,這不是開玩笑嗎,你用個map緩存幾個對象,基本上都運用了享元的思想。
7、代理模式
代理模式用於向較簡單的對象代替創建復雜或耗時的對象。
PS:代理模式用得很廣泛,基本所有大家知道的開源框架,都用到了動態代理。
二、創建模式
1、抽象工廠模式
抽象工廠模式提供了一個協議來生成一系列的相關或者獨立的對象,而不用指定具體對象的類型。它使得應用程序能夠和使用的框架的具體實現進行解耦。在JDK和許多開源框架,比如Spring中隨處可見,它們很容易被發現。任何用於創建對象但返回接口或抽象類的,就是抽象工廠模式了。(any method that is used to create an object but still returns a interface or abstract class)
PS:從英文就可以得出,該模式可以與策略模式結合使用。
2、建造者模式
用於通過定義一個類來簡化復雜對象的創建,該類的目的是構建另一個類的實例。構建器模式還允許實現Fluent接口。
PS:這個在我們業務代碼中使用的場景太廣泛了。比如訂單系統大部分項目都有,訂單對象就是一個復雜對象,我們就可以采用建造者模式來做。
3、工廠方法
只是一個返回實際類型的方法。
PS:這個屬於大家都會的設計模式,不多過介紹。
4、原型模式
使得類的實例能夠生成自身的拷貝。如果創建一個對象的實例非常復雜且耗時時,就可以使用這種模式,而不重新創建一個新的實例,你可以拷貝一個對象並直接修改它。
PS:這個你以為是冷門的設計模式,其實錯了,這個是大熱門的設計模式。比如我們業務代碼,經常要各種DTO、BO、DO、VO轉換,其實就可以參考原型設計模式的思想來做。
5、單例模式
用來確保類只有一個實例。Joshua Bloch在Effetive Java中建議到,還有一種方法就是使用枚舉。
PS:在平時開發中,單例是我們用得最多的了,因為Spring的bean,默認就是單例級別的。單例屬於大家基本都會的設計模式。
三、行為模式
1、責任鏈
通過把請求從一個對象傳遞到鏈條中下一個對象的方式來解除對象之間的耦合,直到請求被處理完畢。鏈中的對象是同一接口或抽象類的不同實現。
PS:凡是帶有Filter
關鍵詞的,基本都在用這個設計模式。在業務代碼使用的場景實在是太多了,用到攔截器的地方基本都在用這個設計模式。
2、命令模式
將命令包裝在對象中,以便可以將其存儲,傳遞到方法中,並像任何其他對象一樣返回。
PS:命令模式使用頻率較高,和策略模式比較像,具體區別可以搜索一下。如果用過Activiti
工作流引擎的朋友可以看一下里面的源碼,很多地方都用到了命令模式。
3、解釋器模式
此模式通常描述為該語言定義語法並使用該語法來解釋該格式的語句。(This pattern generally describes defining a grammar for that language and using that grammar to interpret statements in that format.)
PS:這個比較冷門,肥朝沒怎么用過,你用過的話可以留言告訴肥朝。
4、迭代器模式
提供一個統一的方式來訪問集合中的對象。
PS:這個中間件和基礎框架組的同學可能用得比較多,業務代碼的話用得不多,不過JDK中的這種使用很經典,可以看看。
5、中介者模式
通過使用一個中間對象來進行消息分發以及減少類之間的直接依賴。
PS:看到這個描述不用我多說什么,業務代碼使用的場景太多了。比如你們用MQ,其實就是在用中介者模式。所以肥朝一再強調,即使是每天CRUD,關注肥朝一起學習,也能給你的CRUD項目,加上美顏+濾鏡(設計模式)的加強效果。
6、備忘錄模式
生成對象狀態的一個快照,以便對象可以恢復原始狀態而不用暴露自身的內容。比如Date對象通過自身內部的一個long值來實現備忘錄模式。
PS:這個在業務中使用得不多,據肥朝了解其中一種場景是,你要把數據丟到MQ,但是MQ暫時不可用,那么你把數據暫存到DB,后面再輪詢丟到MQ。如果你有更好的場景,留言告訴肥朝。
7、空對象模式
它允許您抽象空對象的處理。
PS:這個業務代碼用得不多,但是JDK中的這幾個方法我們倒是挺常用的。
8、觀察者模式
用於為組件提供一種靈活地向感興趣的接收者廣播消息的方式。
PS:我們業務代碼一般是基於Zookeeper來做觀察者的。基本上用到ZK的地方,都是在用觀察者模式,比如分布式鎖,比如服務發現等。
9、狀態模式
允許您在運行時根據內部狀態輕松更改對象的行為。
PS:這個在業務代碼用得就太廣泛了,我就不信你們系統還沒有“狀態”了。比如我們常見的訂單狀態或者各種XX狀態,都可以用得上。
10、策略模式
使用這個模式來將一組算法封裝成一系列對象。通過調用這些對象可以靈活的改變程序的功能。
PS:這個太高頻了,常用於優化大量的if-else
,如果這個設計模式都不會,出去不要說關注過肥朝的公眾號!
11、模板方法模式
讓子類可以重寫方法的一部分,而不是整個重寫,你可以控制子類需要重寫那些操作。
PS:這個模式也是非常高頻的模式。業務代碼中經常遇到有很多相同的部分,我們可以做一個抽象類,子類來實現差異化,如果還不知道的,趕緊搜索一下,再次強調,非常高頻。
12、訪問者模式
提供一個方便的可維護的方式來操作一組對象。它使得你在不改變操作的對象前提下,可以修改或者擴展對象的行為。
PS:這個肥朝使用的頻率不高,如果你有在業務代碼中使用,歡迎留言告訴肥朝。
四、寫在最后
你項目都用到了哪些設計模式?亦或者上述設計模式你在實際業務代碼中有更好的場景,歡迎留言。