大神詳解,這麼詳細的Java設計模式不收藏可惜了

2021-01-09 51CTO

引子

設計模式是很多程式設計師總結出來的優秀實踐。曾經在剛開始寫項目的時候學習過設計模式,在開發過程中,也主動或者被動的使用過。現在寫代碼雖說不會特意明確在用哪種設計模式,但潛移默化的寫出來公認的優秀實踐代碼,畢竟看的比較清爽。為什麼再看一遍設計模式,主要有幾個原因:***,很多優秀的源碼基本都使用了設計模式,明確設計模式能夠更好的看源碼。第二,很多中間件設計理念也是基於設計模式的,還有其他的語言,都有自己的設計優秀實踐。對於我來說,設計模式始於java,不止於java。第三,有了這種規範,可以更好的和他人溝通,言簡意賅。

設計模式原則

很多優秀的文章和書籍都講的很明白了,我說下自己的體會。 1.單一職責原則,就是一個類只負責做一件事情。這樣就可以做到解耦合的效果,讓代碼看起來比較清爽,也體現了java的封裝性。還有個原則叫迪米特法則,就是一個對象對另一個對象有儘量少的了解,說的也是解耦合的事情。 2.裡氏替換原則和依賴導致原則,說的是繼承的事情。父類可以做的事情,子類都可以去做,子類可以儘量去依賴父類去做事情;但是反過來,父類不能依賴子類去做一些事情。體現了java的繼承特性。 3.接口隔離原則,接口也應該儘可能的隔離開來。其實類寫多了,的確耦合性低,為了讓他們交流起來,用的最多的就是接口,畢竟只需要知道做什麼,怎麼做,去訪問那個具體的類吧。 4.開閉原則,對修改關閉,對拓展開放。就是代碼需要有很好的延展性,對原有代碼結構不能破壞。

創建者模式

創建者模式就是為了用優雅的方式創建我們使用的類。

1.簡單工廠模式

這個用的比較少,就是有個工廠,告訴你我要什麼東西,你造好了給我就行。比如說:

2.工廠模式

這個其實和簡單工廠模式差不太多,就是將工廠繼續拆分,比如說剛剛EasyBallFactory是一個總工廠,我們現在拆分成SoccerFactory和BasketBallFactory分別生產足球和籃球。某個工廠內部可以根據需求生產不同的產品,比如說soccer可以生產不同大小的出來。

3.抽象工廠模式

抽象工廠模式主要設計產品組的概念,就是某一個工廠生產出配套的一系列產品。例如,在生產足球的同時,SoccerFactory還可以生產與之配套的足球雜誌。

4.單例模式

單例模式有很多種形式,優秀實踐應該是兩重判斷,保證只new出來一個。單例可以說是非常普遍的設計模式了。單例就是指在服務容器的生命周期中只能有這麼一個。比如說Servlet、Spring中注入的Bean等等都是單例的。

5.建造者模式

將一個複雜對象分布創建。如果一個超大的類的屬性特別多,我們可以把屬性分門別類,不同屬性組成一個稍微小一點的類,再把好幾個稍微小點的類竄起來。比方說一個電腦,可以分成不同的稍微小點的部分CPU、主板、顯示器。CPU、主板、顯示器分別有更多的組件,不再細分。

SpringBoot實現了0配置,幾乎所有的配置都寫到了java代碼中,大量的配置不得不讓配置類採用建造者模式,這樣層次比較清晰。

6.原型模式

原型模式用的比較少,用於創建重複對象。需要實現Cloneable 可以選擇重寫clone()方法。clone分為淺克隆和深克隆。淺克隆只是克隆引用,對象還是一個。深克隆是對象也新創建了一個,如下:

結構型模式

上面的設計模式可以幫助我們非常優雅的創建出來對象,下面看幾個對象關係之間的模型。

7.代理模式

Spring的AOP用的是動態代理,何為動態不看了,用過Spring的小夥伴都知道吧。單純看一下最基礎代理模式是什麼樣的。代理就是,一個對象輔助另一個對象去做某件事,同時還可以增加一點輔助功能。例如,你買車,的確是你花錢把車買到了,但是你不可能直接去和廠家談吧,你應該通過4S店購買,同時4S店幫助你入保險扣稅等操作,最終你才得到了你想要的車。

8.適配器模式

適配器,顧名思義,是讓兩個不兼容的東西可以一起工作。例如插座的電源是220V,手機直接給他220V 50HZ的交流電我相信一般都會直接炸了(除了諾基亞...)手機充電器就進行了適配,將電壓變小,交流電變成直流電。除了這種需要改變屬性的操作(比較好說,不舉例子了),適配器還用於在接口繼承方面。假設一個***接口有一大堆方法需要實現類實現,我新寫了個類只是想選擇的實現一兩個接口,那其他的方法我是不是都需要實現一下,即使是空實現(單純實現,不進行任何邏輯操作),這是我們就需要一個適配器類,空實現那些方法,我的新類只需要繼承這個適配器類就好了,要是想實現某個方法,只需要重寫掉配置類中對應的方法就好。這種模式基本都會用到,畢竟誰的代碼還沒個***接口啊。

9.橋接模式

就是用於抽象化和實現化的解耦。又是解耦,貌似設計模式就是教我們如何優雅的解耦。提高了代碼的拓展性,並且可以實現代碼的動態切換。 最開始的Ball、Soccer、BasketBall接著用,增加新的類。

10.裝飾模式

一個裝飾類,在原來類的基礎上增加一點功能。是不是和代理模式很像,我甚至可以將整個代碼搬過來照樣可以說的通的。這兩個模式意思上有點差別,代理模式是原對象做不了那件事,必須讓代理對象去做,主導側重於代理對象,比如說買車。裝飾模式是說,就是讓原對象直接去做這件事,只是功能上增強一點,主導在於原對象。比如說炒菜的時候撒點鹽。

11.外觀模式

又稱門面模式,就是一個門面,一個操作無需讓對象知道其內部實現的複雜度,儘量讓用戶感知到是非常簡單的。這就是為什麼我們controller層儘量(或者說一定)少些業務邏輯,讓controller層只是起到一個傳參和通用性參數校驗的功能,剩下的全交給service去做吧。我們還需要在代碼中不斷將「長得」特別長的代碼封裝成一個方法,「讓處處都有好看的外觀」。看一下我們曾寫過的代碼,這裡只起到了傳參的作用,究竟這個足球是怎麼創建出來的,客戶端不必擔心。

12.組合模式

組合模式是將存在某種包含關係的數據組織在一起,典型的例子就是樹狀結構。例如菜單功能,一個菜單除了自己該有的屬性,還可能包含子菜單,創建的時候可以使用遞歸的方法。

13.享元模式

享元模式儘可能的讓用戶復用已經有的對象,從而避免造成反覆創建對象的資源浪費。首先就會想到資料庫連接池還有String常量池,延伸一下,幾乎所有和緩存有關的代碼,多少都會用到享元模式。享元模式要求大部分的對象可以外部化。這邊要說兩個概念,享元模式對象的屬性可以分為兩個部分,內部狀態和外部狀態,內部狀態是指不會隨環境而改變的值,比如說個人信息,外部狀態是指隨環境改變的值,不能進行共享的信息,如某大學生選修的課程。

行為型模式

創建了對象,對象之間有了結構關係,就要看下怎麼更加優雅的相互作用了。

14.策略模式

定義一組算法, 將每個算法都封裝起來, 並且使它們之間可以互換。可以說是一組算法的封裝,根據客戶端給出的不同要求,進行不同的運算。比如下面這個簡易計算器。

15.觀察者模式

定義了一種一對多的依賴關係,當一個對象(被觀察者)狀態改變的時候,所有依賴於該對象的觀察者都會被通知,從而進行相關操作。很多中間件都依賴於觀察者模式,例如RabbitMQ,還有那些事件驅動模型(好像node就是)。下面舉個例子,被觀察者是監考老師,考試時間結束,通知所有觀察者學生上交試卷。

16.責任鏈模式

責任鏈模式為請求創建一個接收者對象的鏈,對發送者和接受者進行解耦合。filter鏈就是責任鏈模式。

17.模板方式模式

一個抽象類公開定義了執行它的方法的方式/模板。它的子類可以按需要重寫方法實現,但調用將以抽象類中定義的方式進行。SpringBoot為用戶封裝了很多繼承代碼,都用到了模板方式,例如那一堆XXXtemplate。

18.狀態模式

簡單來說,就是一個對象有不同的狀態,根據狀態不同,可能有不同的行為。

19.迭代器模式

提供一個方法,可以順序訪問一個對象內部的各個元素,不需要知道內部構造。現在基本很少自己實現迭代器了,基本成熟的框架或者強大的JDK都會給出訪問的方法,比如說java中iterator。這樣做主要是進一步封裝對象內部的結構,讓行為和結構想耦合。這個不舉例子了,用過iterator這個的小夥伴應該都清楚,就是不停的next,去訪問下一個元素。

20.命令模式

命令模式是將請求以命令的形式包裹在對象中,並傳遞給對象,調用對象尋找到處理該命令的合適的對象,並將該命令傳遞給相應的對象,該對象執行。簡單點說就是不同請求都封裝成一個對象,不同的請求調用不同的執行者。

21.備忘錄模式

相當於做一個快照,在不破壞對象本身結構的情況下,記錄對象的一個狀態,合適的時候可以恢復到這種狀態。資料庫做事務回滾的時候就用了這種方式。這裡需要注意的是,對象不與備忘錄本身耦合,而是跟備忘錄管理類耦合(就是List<備忘錄>),這個好理解,畢竟快照不止一個嘛。

22.訪問者模式

當對特定角色進行訪問的時候,需要通過訪問者進行訪問。一個對象不太方便被你直接訪問的時候,你需要將自己的引用交給訪問者,通過訪問者去訪問該對象。比如說,化學課,想看一個細胞結構,由於肉眼無法直接看到微觀世界的玩意,需要通過顯微鏡間接訪問。

23.中介者模式

降低對象或者說事物之間通訊的複雜性,降低耦合。比如說分布式系統中,不是需要實時反饋的操作,我們無需直接對接,只需將想做的事告訴中間件,中間件告訴另外一個系統。比如說,訪問(用戶點擊)一條新聞操作,同時需要記錄是誰訪問了什麼新聞,同時給新聞瀏覽次數加1,還要實時更新用戶喜好...總之要更新n個資料庫表,甚至還要操作像ES,Mongo等多個中間件數據。但是對於用戶來說,我只是做了一個點擊操作,希望得到的結果就是看條新聞啊,你這麼多操作,搞這麼慢,用戶體驗很差啊,而且並發量也很低,那不如做成兩個小系統,A系統,拉取新聞,推送,並組裝一個信息扔給MQ中間件,ok,結束,用戶看到新聞。然後B系統監聽,得到這個消息,進行各種更新,這裡,這個中間件就是我們的中介。再比如說,MVC中的控制層就是展示層和模型層的中介。再比如說,下面這個聊天室:

24.解釋器模式

構建一種翻譯方式,將某種語言或描述翻譯成我們很好理解的語言或者描述。這裡很好理解的意思是看得懂,看的快。本來我也想舉什麼編譯器這種高大上的,將底層語言甚至機械語言和我們使用的高級程式語言。後來想了想,其實Map就可以看作一個很好的編譯器,key你可以存放一個非常小的字符串,value理論上你可以存放任何東西,所以代碼就不寫了。

【編輯推薦】

【責任編輯:

未麗燕

TEL:(010)68476606】

點讚 0

相關焦點

  • 重學Java 設計模式:實戰命令模式「模擬高檔餐廳八大菜系,小二點單...
    當然如果你開發過一些桌面應用,也會感受到這樣設計模式的應用場景。從這樣的模式感受上,可以想到這是把邏輯實現與操作請求進行分離,降低耦合方便擴展。命令模式是行為模式中的一種,以數據驅動的方式將命令對象,可以使用構造函數的方式傳遞給調用者。調用者再提供相應的實現為命令執行提供操作方法。可能會感覺這部分有一些饒,可以通過對代碼的實現進行理解,在通過實操來熟練。
  • 設計模式之狀態模式(java實現)
    還不理解的話,再來個類圖看看。2、類圖從上圖可以看出,狀態模式所涉及到的角色有3個:(1)環境(Context)角色,也成上下文:定義操作的方法。(2)抽象狀態(State)角色:這裡表示折扣接口,用戶封裝行為。(3)具體狀態(ConcreteState)角色:這裡指具體的折扣類。
  • Java反射機制深入詳解
    反射是java語言的一個特性,它允程序在運行時(注意不是編譯的時候)來進行自我檢查並且對內部的成員進行操作。例如它允許一個java的類獲取他所有的成員變量和方法並且顯示出來。Java 的這一能力在實際應用中也許用得不是很多,但是在其它的程序設計語言中根本就不存在這一特性。例如,Pascal、C 或者 C++ 中就沒有辦法在程序中獲得函數定義相關的信息。
  • 程式設計師:java單例模式,為什麼要加雙重鎖?為什麼要加volatile?
    單例模式單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。
  • Java編程中基礎反射詳細解析
    類加載器負責加載所有的類,系統為所有加載到內存中的類生成一個java.lang.Class 的實例。被編譯後的Java文件.class也被JVM解析為一個對象,這個對象就是java.lang.Class。這樣當程序在運行時,每個java文件就最終變成了Class類對象的一個實例。我們通過Java的反射機制應用到這個實例,就可以去獲得甚至去添加改變這個類的屬性和動作,使得這個類成為一個動態的類。
  • Java 反射:框架設計的靈魂
    動態語言:是指程序在運行時可以改變自身結構,在運行時確定數據類型,一個對象是否能執行某操作,只取決於它有沒有對應的方法,而不在乎它是否是某種類型的對象;比如 JavaScript、Python。Class clz = Class.forName("java.util.ArrayList");Method method_add = clz.getMethod("add",Object.class);Constructor constructor = clz.getConstructor();Object object
  • 設計模式之狀態模式總結篇
    狀態模式總結篇狀態模式總結篇,我們將從以下幾個方面對狀態模式進行總結。狀態模式出現的意圖是什麼?通過對象內部狀態發生改變進而來改變對象的行為,對象看起來好像是被修改了一樣。本文出處凱哥Java(kaigejava)講《23種設計模》系列教程種的《狀態模式總結篇》主要解決的問題是什麼?對象的行為依賴於對象的狀態變化(屬性變更),並且根據屬性值(狀態)的改變而改變相關的行為。如,出不出糖果這個行為受糖果機裡面有沒有糖果和有沒有投幣這兩個狀態影響而改變的。什麼時候或者是什麼場景下使用狀態模式?
  • Java經典面試題Spring是什麼 Spring框架入門詳解
    我們平時創建對象需要自己手動創建,現在對象都是通過spring容器ApplicationContext創建,這就是所謂的IOC控制反轉,如果有了解工廠設計模式的朋友會更容易理解,ApplicationContext此處就相當於一個工廠類。我之前講解MyBatis框架的SqlSession就是由SqlSesionFactory創建的。
  • 6.java設計模式之適配器模式
    基本需求:將一個220V的電壓輸出成5V的電壓,其中220V電壓為被適配者,變壓器為適配器,5v電壓為適配目標基本介紹:適配器模式屬於結構型模式,將某個類的接口轉換成客戶端期望的另一個接口表示,主的目的是兼容性,讓原本因接口不匹配不能一起工作的兩個類可以協同工作。
  • 開發崗位這麼多,為什麼選Java?你學Java了嗎-開課吧
    提到C++語言,很多人發現在使用過程中最容易出現的錯誤就是內存管理,而java有自動垃圾回收器,不用擔心內存。時不等人,抓緊時間開始學習之旅吧。學習沒有捷徑,希望大家都能少走一些彎路,學有所成!Java語言相關內容推薦:
  • 用最傻瓜式的方法理解Java中的封裝、繼承和多態
    說到java中面向對象的封裝、繼承和多態,很多人會說這麼簡單這麼入門的東西一直講幹嘛,雖然是基礎,但是我們要明白,所有東西都是要在基礎上發展的,沒有基礎就去學其他的,那麼你肯定是很容易失敗的,那麼應該怎樣能夠用傻瓜式方法去理解Java面向對象的封裝、繼承和多態呢?
  • 迷你世界:大神最愛用的4種多功能道具,非常實用,建議收藏!
    在創造模式中,大部分道具都能任意使用,其他的則需要合成或者打怪掉落。道具雖然很多,自然其中便有些很厲害的道具,歡迎閱讀本期資訊。迷你世界:大神最愛用的4種多功能道具,非常實用,建議收藏!1:火種。古有普羅米修斯為人類偷火種,今有玩家用火種拯救迷你世界。火種從本質上來說是輔助道具,自身完全沒有任何能力。
  • 設計模式之策略模式(Java實現例子說明)
    下面我們代碼去實現一遍就能很清楚的理解了,第一步:定義抽象策略接口第二步:具體策略類第三步:環境類實現三、分析策略模式1、為什麼要使用策略模式?策略模式的優點:我們之前在選擇出行方式的時候,往往會使用if-else語句,也就是用戶不選擇A那麼就選擇B這樣的一種情況。
  • CF人機爆破模式玩法詳解 潛伏者與保衛者分析
    ­  CF人機爆破模式玩法詳解,潛伏者與保衛者分析。CF人機爆破模式中潛伏者與保衛者哪個更加合適呢?往往對戰人機的時候很多玩家處於少數,也有很多大神被人機爆破打的體無完膚,在人機爆破模式的當中尤其是新手們對與陣營的選擇非常重要,我們來一起看看大神們是怎樣說的吧。
  • 收藏!活性汙泥法中汙泥濃度MLSS詳解!
    收藏!活性汙泥法中汙泥濃度MLSS詳解!北極星水處理網訊:活性汙泥法的運行需要眾多控制參數的合理調控,其中包括活性汙泥濃度(MLSS)的控制,它是汙水系統日常運行中最常用的指標之一。對此,今天針對MLSS的定義和其他指標關係進行詳細的介紹。 1.
  • 詳解Java表達式與運算符
    在java語言中,定義常量的語法如下:final 數據類型 常量名稱 = 值;其中,final是Java關鍵字,數據類型可以是Java語言支持的任何數據類型。在java語言中,運算符可分為5種類型:算術運算符、賦值運算符、關係運算符、邏輯運算符、位運算符。根據操作數的不同,運算符又分為單目運算符、雙目運算符和三目運算符。單目運算符只有一個操作數,雙目運算符有兩個操作數,三目運算符則有三個操作數。
  • Java研發技術——Volatile原理詳解
    ,而是先將系統內存的數據讀到內部緩存(L1,L2或其他)後再進行操作,但操作完不知道何時會寫到內存。重排序重排序是指編譯器和處理器為了優化程序性能在不影響程序執行結果的前提下而對指令序列進行重新排序的一種手段。
  • Java8 lambda表達式語法
    但是有一點這裡強調一下(Windows系統):目前我們工作的版本一般是java 6或者java 7,所以很多人安裝java8基本都是學習為主。這樣就在自己的機器上會存在多版本的JDK。而且大家一般是希望在命令行中執行java命令是基於老版本的jdk。但是在安裝完jdk8並且沒有設置path的情況下,你如果在命令行中輸入:java -version,屏幕上會顯示是jdk 8。
  • Java面向對象之final、abstract抽象、和變量生命周期
    只要滿足以下條件就可以考慮把一個類設計成final類:在設計之初就考慮不進入繼承體系的類。出於安全考慮,類的實現細節不允許被拓展和修改。比如:基本數據類型的包裝類就是一個典型的例子。該類不會再被拓展。在父類中提供了統一的算法骨架,不允許子類通過方法覆蓋來修改其實現細節, 此時使用final修飾。比如在模板方法設計模式中。在構造器中調用的方法(初始化方法),此時一般使用final修飾。這也是構造器不能被繼承的原因。
  • AQS設計思想與重要欄位詳解
    本文基於JDK1.8本篇學習目標了解AQS的設計思想以及重要欄位含義,如通過state欄位表示同步狀態等。了解AQS內部維護鏈式雙向同步隊列的結構以及幾個重要指針。了解五種重要的同步狀態。明確兩種模式:共享模式和獨佔模式。學習兩種模式下AQS提供的模板方法:獲取與釋放同步狀態相關方法。