前端常用設計模式

来源:https://www.cnblogs.com/dengyao-blogs/archive/2023/11/07/17815827.html
-Advertisement-
Play Games

什麼是設計模式? ​ 設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結,設計模式並不是一種固定的公式,而是一種思想,是一種解決問題的思路;使用設計模式是為了可重用代碼,讓代碼更容易被他人理解,保證代碼可維護性。 設計模式不區分編程語言,設計模 ...


什麼是設計模式?

​  設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結,設計模式並不是一種固定的公式,而是一種思想,是一種解決問題的思路;使用設計模式是為了可重用代碼,讓代碼更容易被他人理解,保證代碼可維護性。

  設計模式不區分編程語言,設計模式是解決通用問題和提效的解決方案;通常在我們解決問題的時候,很多時候不是只有一種方式,我們通常有多種方式來解決;但是肯定會有一種通用且高效的解決方案,這種解決方案在軟體開發中我們稱它為設計模式;

  項目中合理的運用設計模式可以完美的解決很多問題,每種模式在現實中都有相應的場景及其原理來與之對應,每一個模式描述了一個在我們周圍不斷重覆發生的問題,以及該問題的核心解決方案,這也是它能被廣泛應用的原因。

什麼是設計原則?

  設計原則是基於設計模式產生的一套方法論;通常在做很多事情的時候,都會有一定的規範制約;在軟體開發的過程中,我們可以將設計原則視為一種約定俗成的開發規範,但不是必須要遵循的;

  • 單一職責原則(Single Responsibility Principle)
  • 開閉原則(Open Closed Principle)
  • 里氏替換原則(Liskov Substitution Principle)
  • 迪米特法則(Law of Demeter)
  • 介面隔離原則(Interface Segregation Principle)
  • 依賴倒置原則(Dependence Inversion Principle)

  6 個原則的首字母(里氏替換原則和迪米特法則的首字母重覆,只取一個)聯合起來就是:SOLID(穩定的),其代表的含義也就是把這 6 個原則結合使用的好處:建立穩定、靈活、健壯的設計;

設計原則

  • 單一職責原則(Single Responsibility Principle)

    一個類只做一件事;一個類應該只有一個引起它修改的原因,應該只有一個職責。每一個職責都是變化的一個軸線,如果一個類有一個以上的職責,這些職責就耦合在了一起。導致脆弱的設計。例如:要實現邏輯和界面的分離

  • 開閉原則(Open Closed Principle)

   一個軟體實體如類,模塊和函數應該對擴展開放,對修改封閉,即在程式需要進行拓展的時候,不能去修改原有的代碼。

  • 里氏替換原則(Liskov Substitution Principle)

   不要破壞繼承體系;程式中的子類應該可以替換父類出現的任何地方並保持預期不變。所以子類儘量不要改變父類方法的預期行為。

  • 迪米特法則(Law of Demeter)

   降低耦合度,一個類或對象應該對其它對象保持最少的瞭解。只與直接的朋友(耦合)通信,不與朋友的朋友通信。

  • 介面隔離原則(Interface Segregation Principle)

   設計介面的時候要精簡單一;當類 A 只需要介面 B 中的部分方法時,因為實現介面需要實現其所有的方法,於是就造成了類 A 多出了部分不需要的代碼。這時應該將 B 介面拆分,將類A需要和不需要的方法隔離開來。

  • 依賴倒置原則(Dependence Inversion Principle)

   細節應該依賴於抽象 ,抽象不依賴於細節;把抽象層放在程式設計的最高層,並保持穩定,程式的細節變化由低層的實現層來完成。(例如實現一個組件基類,存放組件的id、apperance等信息,具體的組件類繼承基類,實現具體的UI及功能 )

為什麼要使用設計模式?

  1. 設計模式是前人根據經驗總結出來的,使用設計模式,就相當於是站在了前人的肩膀上。
  2. 設計模式使程式易讀。熟悉設計模式的人應該能夠很容易讀懂運用設計模式編寫的程式。
  3. 設計模式能使編寫的程式具有良好的可擴展性,滿足系統設計的開閉原則。
  4. 設計模式能降低系統中類與類(或者function與function)之間的耦合度。
  5. 設計模式能提高代碼的重用度。
  6. 設計模式能為常見的一些問題提供現成的解決方案。
  7. 設計模式增加了重用代碼的方式。比如裝飾器模式,在不使用繼承的前提下重用系統中已存在的代碼。

設計模式分類

  •  5種創建型
  •  7種結構型
  •  11種行為型
  • 創建型:抽工單建原型

   抽象工廠、工廠、單例、建造者、原型

  •  結構型:橋代理裝飾適配器,享元組合成門面

      橋接、代理、裝飾器、適配器、享元、組合、門面(外觀)

  •  行為型:觀察模板迭代的狀態,命令中介解釋職責鏈,訪問策略備忘錄

   觀察者、模板、迭代、狀態、命令、中介者、解釋器、職責鏈、訪問者、策略、備忘錄

日常工作常用的設計模式

  發佈-訂閱模式(觀察者模式):

  定義:

    發佈—訂閱模式又叫觀察者模式,它定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都將得到通知;發佈訂閱模式有發佈訂閱調度中心(中間商),觀察者模式沒有!

  應用場景:

  DOM元素節點事件實時觸發方法
  vue的響應式原理

  大白話解釋(生活中的場景):

  假設你在淘寶上看上了某件商品,臨近雙11,但是價格有點高;於是你訂閱了某種類型某種規格的商品降價通知,到雙11降價的時候會系統推送相關消息給對應的用戶;這時發佈-訂閱模式就產生了;用戶是訂閱者,淘寶是調度中心,商家是發佈者;商家降價之後,會通過發佈中心推送相關的消息給指定的訂閱者;

 1 // 定義一個發佈者對象
 2 var pub = {
 3     // 緩存列表,存放訂閱者回調函數
 4     list: {},
 5     subscribe: function (key, fn) {
 6         // 如果沒有該消息的緩存列表,就創建一個空數組
 7         if (!this.list[key]) {
 8             this.list[key] = [];
 9         }
10         // 將回調函數推入該消息的緩存列表
11         this.list[key].push(fn);
12     },
13 
14     // 取消訂閱方法
15     unsubscribe: function (key, fn) {
16         // 如果有該消息的緩存列表
17         if (this.list[key]) {
18             // 遍歷緩存列表
19             for (var i = this.list[key].length - 1; i >= 0; i--) {
20                 // 如果存在該回調函數,就從緩存列表中刪除
21                 if (this.list[key][i] === fn) {
22                     this.list[key].splice(i, 1);
23                 }
24             }
25         }
26     },
27     // 發佈方法
28     publish: function () {
29         // 獲取消息類型
30         var key = Array.prototype.shift.call(arguments);
31         // 獲取該消息的緩存列表
32         var fns = this.list[key];
33         // 如果沒有訂閱消息,就返回
34         if (!fns || fns.length === 0) {
35             return;
36         }
37         // 遍歷緩存列表,執行回調函數
38         for (var i = 0; i < fns.length; i++) {
39             fns[i].apply(this, arguments);
40         }
41     }
42 }
43 
44 // 定義一個訂閱者對象A
45 var subA = function (name) {
46     console.log('A收到了消息:' + name);
47 }
48 
49 // 定義一個訂閱者對象B
50 var subB = function (name) {
51     console.log('B收到了消息:' + name);
52 }
53 
54 // A訂閱了test消息
55 pub.subscribe('test', subA);
56 // B訂閱了test消息
57 pub.subscribe('test', subB);
58 // 發佈了test消息,傳遞了參數'hello'
59 pub.publish('test', 'hello');
60 // A取消訂閱了test消息
61 pub.unsubscribe('test', subA);
62 // 發佈了test消息,傳遞了參數'world'
63 pub.publish('test', 'world');
64 
65 // 輸出:
66 // A收到了消息: hello
67 // B收到了消息: hello
68 // A取消訂閱了test消息

  代理模式:
   定義:
    為一個對象提供一個代用品或占位符,以便控制對它的訪問!
  應用場景:
    Proxy代理對象;
     圖片預載入,占位loading圖片就是代理;

  大白話解釋(生活中的場景):

  明星往往擁有很多粉絲,也會接收到很多粉絲送的禮物;但是這些禮物一般都是通過 粉絲 ->  經紀人  ->  明星 這個流程才到達明星的手裡;這裡的經紀人就是明星的代理對象,有些無用或者惡作劇之類的禮物,可以直接在代理對象(經紀人)這一層直接攔截或者過濾掉;
 1 var fans = {
 2     flower() {
 3         agent.reception('花');
 4     }
 5 }
 6 
 7 var agent = {
 8     reception: function (gift) {
 9         console.log('粉絲送的:' + gift); // 粉絲送的:花
10         if (gift !== '花') {
11             star.reception('花');
12         }
13     }
14 }
15 
16 var star = {
17     reception: function (gift) {
18         console.log('收到粉絲的:' + gift);
19     }
20 }
21 
22 fans.flower();

  策略模式:
  定義:
    定義一系列演算法,並將這些演算法各自封裝成策略類(方法),然後將不變的部分和變化的部分分離開來,並且這些演算法可以相互替換
  應用場景:
    主要用來消除或減少邏輯分支判斷,避免冗長的if-else或switch分支判斷

  大白話解釋(生活中的場景):

  政府事務辦理中心,是近幾年來提升居民、市民辦事的一項策略調整;在政務中心沒出現之前,市民辦事都需要去對應的政府機關視窗分流辦理相應手續;政務大廳的出現將公安、財務、勞動、稅務、供電等多個部門事務辦理手續集中到政務中心來辦理,這樣提高了各級機關單位的辦事效率,減少了維護辦事人群的秩序,也提升了市民的用戶體驗;市民只需要記住辦理政務相關手續去政務大廳即可;

 1 /** 策略模式改造前 */
 2     function calculateBonus(level,salary){
 3         if(level === 'S'){
 4             return salary*4;
 5         }
 6         
 7         if(level === 'A'){
 8             return salary*3
 9         }
10 
11         if(level === 'B'){
12             return salary*2
13         }
14     }
15 
16     console.log(calculateBonus("S",14000));  //56000
17     console.log(calculateBonus("A",10000)); //30000
18     console.log(calculateBonus("B",5000));  //10000
 1 /** 策略模式改造後*/
 2     var strategies  = {
 3         "S":function(salary){
 4             return salary*4
 5         },
 6         "A":function(salary){
 7             return salary*3;
 8         },
 9         "B":function(salary){
10             return salary*2
11         }
12     }
13 
14     var calculateBonus =function(level,salary){
15         return strategies[level](salary);
16     } 
17     console.log(calculateBonus("S",14000));  //56000
18     console.log(calculateBonus("A",10000));  //30000
19     console.log(calculateBonus("B",5000));   //10000

  單例模式
   定義:
    保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
  應用場景:
    彈窗組件;
     載入某個script資源或者只能存在一個全局變數;
     React狀態管理工具Redux
  大白話解釋(生活中的場景):

  假設甲去當地派出所辦理身份證相關手續,這時公安機關會對甲的身份進行驗證查詢,如果甲已經有過身份登記信息,就直接辦理掛失補辦手續;否則走新增戶籍人手續;一個合法公民不可能同時存在兩張合法身份證件;

 1 let Singleton = function (name) {
 2     this.name = name;
 3     this.instance = null;
 4 }
 5 
 6 Singleton.prototype.getName = function () {
 7     console.log(this.name);
 8 }
 9  
10 Singleton.getInstance = function (name) { 
11     if (this.instance) {
12         return this.instance;
13     }
14     return this.instance = new Singleton(name);
15 }
16 
17 let Winner = Singleton.getInstance('Winner');
18 let Looser = Singleton.getInstance('Looser');
19 
20 console.log(Winner === Looser); // true
21 console.log(Winner.getName()); // 'Winner'
22 console.log(Looser.getName()); //  'Winner'

  總結

  1. 在日常開發中,應該儘可能的遵守設計原則和合理選用設計模式;
  2. 合理使用設計模式便於我們寫出可維護性高、拓展性強的代碼;
  3. 設計模式一共分為三大類,分別是 :5種創建型、7種結構型、11種行為型;
  4. 設計模式不區分編程語言,設計模式是解決通用問題和提效的解決方案;
  5. 編程的目的是解決現實問題,同樣每一種設計模式的原理都能在現實社會中找到對應的場景,這也是它能被廣泛應用的根本原因;

 

作者:有夢想的鹹魚前端 出處:https://www.cnblogs.com/dengyao-blogs/ 本文版權歸作者和博客園共有,歡迎轉載,但必須給出原文鏈接,並保留此段聲明,否則保留追究法律責任的權利。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文分享自華為雲社區《GaussDB資料庫SQL系列-數據去重》,作者: Gauss松鼠會小助手2 。 一、前言 數據去重在資料庫中是比較常見的操作。複雜的業務場景、多業務線的數據來源等等,都會帶來重覆數據的存儲。本文以GaussDB資料庫為實驗平臺,將為大家詳細講解如何去重。 二、數據去重應用場景 ...
  • 本篇文章記錄最近ES做節點替換,從shard遷移過程中被鎖定導致無法分配,主shard正常,希望可以幫助其它人 failed to create shard,failed to obtain in-memory shard lock,ShardLockObtainFailedException 一、 ...
  • 設置進程記憶體(Process Memory) Apache Flink通過嚴格控制其各種組件的記憶體使用,在JVM之上提供高效的工作負載。 配置總記憶體(Total Memory) Flink JVM進程的總進程記憶體(total process memory)由Flink應用程式消耗的記憶體(總Flink ...
  • 本文是對這篇文章How the MySQL Optimizer Calculates the Cost of a Query (Doc ID 1327497.1)[1]的翻譯,翻譯如有不當的地方,敬請諒解,請尊重原創和翻譯勞動成果,轉載的時候請註明出處。謝謝! 適用於: MySQL 4.0 及後續更 ...
  • 本文分享自天翼雲開發者社區《一種Mysql和Mongodb數據同步到Elasticsearch的實現辦法和系統》,作者:l****n 核心流程如下: 核心邏輯說明: MySQL Binlog解析: 首先,從MySQL的二進位日誌(Binlog)中解析出表名。這一步驟非常關鍵,因為我們只關註特定表的數 ...
  • 在Oracle資料庫中,有時候需要根據實際情況調整redo log的大小,增加redo log的日誌組的數量,或者增加日誌組成員,以及redo log的size大小不合適時,需要調整redo log的大小(刪除redo log,重新添加redo log),一般情況下,都是手工寫腳本,如果多台資料庫實 ...
  • 本章將深入探討 HarmonyOS 應用開發的關鍵方面,包括應用的生命周期、數據存儲和網路訪問。瞭解這些內容對於創建功能豐富、高效的 HarmonyOS 應用至關重要。 ...
  • 正常情況下,我們按照下麵的步驟操作即可進入Android的開發者模式(大部分安卓手機進入的方式都類似): 打開手機的設置,點擊最下麵的關於手機。 點擊這裡的“HarmonyOS版本”。連續點擊多次(我的手機是7次),然後會彈出需要輸入密碼解屏。解鎖之後屏幕上會提示“您正處於開發者模式!”。 返回到上 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...