一、什麼是設計模式
定義:設計模式是一套被反覆使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總結。在面向對象軟件設計過程中針對特定問題的優雅而簡潔的解決方案。
設計模式遵循一下幾種原則:
1、開閉原則:對擴展開放,對修改關閉
2、單一職責原則:一個類只負責一個功能領域中的相應職責
3、里氏代換原則:所有引用基類的地方必須能透明地使用其子類的對象
4、依賴倒轉原則:依賴於抽象,不能依賴於具體實現
5、接口隔離原則:類之間的依賴關係應該建立在最小的接口上
6、合成/聚合複用原則:儘量使用合成/聚合,而不是通過繼承達到複用的目的
7、最少知道原則:一個軟件實體應當儘可能少的與其他實體發生相互作用
二、為什麼要了解設計模式
設計模式說白了就是前輩們對自己代碼經驗的總結,目的是為了讓我們在遇到類似或相同的問題的時候有經驗可以參考或借鑑使用,使得代碼可複用、更容易被他人理解。
1、設計模式可以讓你知道在某些場景下如何設計出適合該場景的架子。如果只追求去實現一個功能,沒有做其他的考慮,以後需要增加新功能或者做一些改動的時候,可能就會將代碼改的面目全非,難以維護,不熟悉代碼的人接手幹活的話,會出現根本無從下手的問題;
2、如果想要提高自己的能力,去學習一些框架或者庫的源碼的時候,瞭解設計模式也有助於去理解源碼當中應用到的一些設計思想,幫助自己更好的成長;
三、前端中常見的設計模式
設計模式按照分類分為三大類:創建型模式、結構型模式、行為型模式;總共是有23種設計模式。在這裡我只想根據我做過的項目經驗和自己學習設計模式過程中的一些理解來談一談前端中常見的幾種設計模式。通過介紹主要思想結合案例的代碼去和大家一起分享以下的幾種設計模式。
1、工廠模式
什麼是工廠模式?工廠模式是用來創建對象的一種最常用的設計模式。我們不暴露創建對象的具體邏輯,而是將邏輯封裝在一個函數中,那麼這個函數就可以被視為一個工廠。說白了就是像工廠一樣重複的產生類似的產品,工廠模式只需要我們傳入正確的參數,就能生產類似的產品;
生活中的實例:我們去飯店吃飯,只需要知道菜名,飯店後廚就能夠做出相應的菜,而不需要關注具體每道菜的材料、調料以及烹飪方法。
工廠模式的分類:工廠模式根據抽象程度的不同可以分為:
a、簡單工廠
b、工廠方法
c、抽象工廠
工廠模式的優點:我們可以在不動之前原邏輯的基礎上,繼承和拓展新的功能,這樣我們就可以提高效率,之前寫好的功能可以複用,而且可以站在前人的肩膀上,不斷拓展。
在實際的項目中,我們常常需要根據用戶的權限來渲染不同的頁面,高級權限的用戶所擁有的頁面有些是無法被低級權限的用戶所查看。所以我們可以在不同權限等級用戶的構造函數中保存該用戶能夠看到的頁面,再根據權限實例化用戶。
超級管理員:首頁、活動頁面、數據管理、權限管理
管理員:首頁、活動頁面、數據管理
普通用戶:首頁、活動頁面
function UserFactory(role) {
return new this[role]();
}
//工廠方法函數的原型中設置所有對象的構造函數
UserFactory.prototype = {
superAdmin: function () {
this.name = "超級管理員";
this.auth = ["首頁", "活動", "數據管理", "權限管理"];
},
admin: function () {
this.name = "管理員";
this.auth = ["首頁", "活動", "數據管理"];
},
user: function () {
this.name = "普通用戶";
this.auth = ["首頁", "活動"];
},
vipUser: function () {
this.name = "超級心悅會員";
this.auth = ["首頁", "活動", "數據管理", "權限管理", "心悅會員專享福利"];
},
};
根據獲取到的用戶角色信息,直接通過工廠模式,new 一個UserFactory的實例出來,獲取到對應的頁面權限直接渲染展示出來。
2、單例模式
什麼是單例模式?限制類實例化次數只能一次,一個類只有一個實例,並且提供可全局訪問的點。
單例模式的實現:保證一個類只有一個實例, 一般先判斷實例是否存在,如果存在直接返回, 不存在則先創建再返回,這樣就可以保證一個類只有一個實例對象。
1、我們前端應用在使用websocket通信的時候,首先會創建一個websocket連接但是如果過多的websocket連接會佔用大量的服務端的資源,因此一個頁面不可能也沒必要初始化多個相同接口的websocket連接 ,一個應用當中不管有多少頁面,都可以共享同一個連接;
2、項目中引入第三方庫時,重複多次加載庫文件時,全局只會實例化一個庫對象,如 jQuery,lodash,moment ..., 其實它們的實現理念也是單例模式;
3、當我們在逛購物網站的時候,我們可以在不同的產品頁面,看到自己喜歡的商品後加入到購物車當中,此時購物車不會是多個重複的實例,只會生成一個實例;
3、發佈-訂閱模式
什麼是發佈-訂閱模式?它定義了對象間的一種一對多的關係,讓多個訂閱者對象同時監聽某一個主題對象,當一個對象發生改變時,所有依賴於它的對象都將得到通知。
生活中的案例:我想要買房子,我去我看中的樓盤的售樓處去詢問,但是樓盤還沒有開盤,銷售人員讓我關注他們樓盤的一個公眾號,當樓盤開盤以後,這個公眾號會發佈一個通知,我們接收到這個通知以後,就可以去買房了。
這裡我就是訂閱者,銷售就是發佈者,當樓盤開盤的時候,銷售人員在公眾號上發佈了一條消息,我接受到了這個消息,我就可以過去買房。有很多人和我一樣都想要買這個樓盤的房子,都關注了這個公眾號,但是每個人接收到樓盤開盤的消息以後具體做什麼,有的人去買房了,有的人不想買了,銷售人員管不了,他只管在公眾號上發佈消息;
什麼時候使用發佈-訂閱模式:
a、各模塊相互獨立
b、存在一對多的依賴關係
c、依賴模塊不穩定、依賴關係不穩定
d、各模塊由不同的人員、團隊開發
發佈-訂閱模式的優點
a、發佈-訂閱模式廣泛應用於異步編程之中,是一種替代回調函數的方案.多個事件處理函數可以訂閱同一個事件,當該事件發生後,與其相對應的多個事件處理函數都會運行。
b、一個對象不用再顯示的調用另外一個對象的某個接口,降低模塊之間的耦合程度,雖然不清楚彼此的細節,但是不影響他們之間相互通信
1、dom事件
對一個dom節點的事件進行監聽,當操作dom節點時,觸發相應的事件,相應的函數執 行。事件函數對dom節點完全未知,不用去理會是什麼事件,如何觸發,執行就好。
document.body.addEventListener(“click”,function() {…})
2、自定義事件
假如小明想去看周杰倫的演唱會,但是周杰倫演唱會的門票太火爆,一開始買票瞬間就被搶光了。但是有些人可能只是搶到票了,最終沒有去付款,這樣的話在一定時間沒有付款的話,訂單失效,票就會釋放出來供大家去搶。所以我在搶票的網站訂閱了演唱會餘票提醒,只要一有餘票,就會通知小明去搶。
4、裝飾器模式
什麼是裝飾器模式?是為了給一個函數賦能,增強它的某種能力,它能動態的添加對象的行為,對現有的類對象進行包裹和封裝,以期望在不改變類對象及其類定義的情況下,為對象添加額外功能。
什麼是裝飾器模式:是為了給一個函數賦能,增強它的某種能力,它能動態的添加對象的行為,對現有的類對象進行包裹和封裝,以期望在不改變類對象及其類定義的情況下,為對象添加額外功能。
react當中的高階函數就是裝飾器模式的一個最常見的應用;
5、適配器模式
什麼是適配器模式?適配器用來解決兩個已有接口之間不匹配的問題,它並不需要考慮接口是如何實現,也不用考慮將來該如何修改;適配器不需要修改已有接口,就可以使他們協同工作;
適配器模式的優點:
a、已有的功能如果只是接口不兼容,使用適配器適配已有功能,可以使原有邏輯得到更好的複用,有助於避免大規模改寫現有代碼;
b、可擴展性良好,在實現適配器功能的時候,可以調用自己開發的功能,從而方便地擴展系統的功能;
c、靈活性好,因為適配器並沒有對原有對象的功能有所影響,如果不想使用適配器了,那麼直接刪掉即可,不會對使用原有對象的代碼有影響;
1、地圖組件
2、我們都知道很多UI組件或者工具庫會按指定的數據格式進行渲染,但是這個時候 後端是不知道的; 所以可能接口出來的數據我們是不能直接正常的在頁面上渲染的, 而此時老闆催促我們趕緊上線,而後端堅持認為數據格式沒問題,堅決不修改;這個時候我們可以通過適配器模式來前端格式化數據;
四、總結和感想
設計模式並不是單一的某種方法也沒有固定的適用場景。很多時候可能我們自己在寫代碼的時候可能已經在使用某種設計模式的思想但是我們自己卻不知道。我覺得學習設計模式只是單純的去看相關的書籍和博客並不能夠深入的去理解,我覺得在學習的過程中結合自己的項目經驗能夠感悟到其中的精髓才能夠掌握這個思想。設計的再厲害,性能很差,也是一個很差的設計。所以最適合的就是最好的。我希望大家都能夠在實際的工作過程中不斷的去思考和總結怎樣寫出更好的代碼,在前端的道路上能夠走的更遠。