設計模式:程式員跳不開的坑

来源:https://www.cnblogs.com/shiyanlou/archive/2020/05/26/12967293.html
-Advertisement-
Play Games

任何一個有趣、有用的程式、項目或者游戲,都需要堅實的基本功方能實現,設計模式就是我們必學的基本功。 ...


學編程,總是逃不了要學“演算法”,也總跳不開要學“設計模式”。

無論學習什麼語言,設計模式始終是我們必須掌握的,這是程式員的基本功。

設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。

使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的,設計模式使代碼編製真正工程化,設計模式是軟體工程的基石,如同大廈的一塊塊磚石一樣。

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

今天給大家推薦的新課《Go 語言實現 23 種設計模式》,教程涉及7大設計原則、23種設計模式,每種設計模式都從定義、應用及Golang實例三個部分進行詳細介紹。

本課需要學員對 Go 語言有一定的基礎哦,可先學習《Go 語言簡明教程》之後再來學習本課。

本課程概念較多,受篇幅限制,不宜放過多文字,下麵截取課程第一章內容給大家介紹第1種設計原則——開閉原則的概念,想要學習完整設計原則及設計模式的小伙伴請移步至《Go 語言實現 23 種設計模式》學習整個課程

開閉原則

開閉原則(Open Closed Principle,OCP) 由勃蘭特.梅耶(Bertrand Meyer)提出,他在 1988 年的著作《面向對象軟體構造》( Object Oriented Software Construction)中提出:軟體實體應當對擴展開放,對修改關閉(Software entities should be open for extension, but closed for modification),這就是開閉原則的經典定義。

開閉原則是設計模式中的總原則,開閉原則就是說:對拓展開放、對修改關閉。模塊應該在儘可能不修改代碼的前提下進行拓展,這就需要使用介面和抽象類來實現預期效果。我們舉例說明什麼是開閉原則,以 4s 店銷售汽車為例,其類圖如圖所示:

ICar 介面定義了汽車的兩個屬性:名稱和價格。BenzCar 是一個賓士車的實現類,代表賓士車的總稱。Shop4S 代表售賣的 4S 店,ICar 介面的代碼清單如下:

<pre> package main
 import "fmt"
 type ICar interface {
 // 車名
 GetName() string
 // 價格
 GetPrice() int
 }
 copy</pre>

一般情況下 4S 店只出售一種品牌的車,這裡用賓士為例,代碼清單如下

<pre> type BenzCar struct {
    name string
    price int
 }
 func (b BenzCar) GetName() string {
    return b.name
 }
 func (b BenzCar) GetPrice() int {
    return b.price
 }
 copy</pre>

這裡我們模擬一下 4s 店售車記錄:

<pre> func main() {
    var (
        list []ICar
    )
    list = []ICar{}
    list = append(list,&BenzCar{"邁巴赫",130})
    list = append(list,&BenzCar{"AMG",343})
    list = append(list,&BenzCar{"V",60})
    for _,v := range list {
        fmt.Println("車名:",v.GetName(),"\t價格:",v.GetPrice())
    }
 }
 copy</pre>

接下來,我們在命令行中輸入 cd Principle 先切換到 go 文件所在目錄下,然後執行 go run 1.go 來看我們的執行結果。如下圖所示:

暫時來看,以上設計是沒有啥問題的。但是,某一天,4s 店老闆說賓士轎車統一要收取一筆金融服務費,收取規則是價格在 100 萬元以上的收取 5%,50~100 萬元的收取 2%,其餘不收取。為了應對這種需求變化,之前的設計又該如何呢?

目前,解決方案大致有如下三種:

  1. 修改 ICar 介面:在 ICar 介面上加一個 getPriceWithFinance 介面,專門獲取加上金融服務費後的價格信息。這樣的後果是,實現類 BenzCar 也要修改,業務類 Shop4S 也要做相應調整。ICar 介面一般應該是足夠穩定的,不應頻繁修改,否則就失去了介面鍥約性了。
  2. 修改 BenzCar 實現類:直接修改 BenzCar 類的 getPrice 方法,添加金融服務費的處理。這樣的一個直接後果就是,之前依賴 getPrice 的業務模塊的業務邏輯就發生了改變了,price 也不是之前的 price 了。
  3. 使用子類拓展來實現:增加子類 FinanceBenzCar,覆寫父類 BenzCar 的 getPrice 方法,實現金融服務費相關邏輯處理。這樣的好處是:只需要調整 Shop4S 中的靜態模塊區中的代碼,main 中的邏輯是不用做很大的修改的。

新增的 FinanceBenzCar 類代碼清單如下:

<pre> type FinanceBenzCar struct {
    BenzCar
 }
 func (b FinanceBenzCar) GetPrice() int {
    // 獲取原價
    selfPrice := b.price
    var finance int
    if selfPrice >= 100 {
        finance = selfPrice + selfPrice5/100    } else if selfPrice >= 50 {        finance = selfPrice + selfPrice2/100
    } else {
        finance = selfPrice
    }
    return finance
 }
 copy</pre>

主函數:

<pre> func main() {
    var (
        list []ICar
    )
    list = []ICar{}
    list = append(list,&FinanceBenzCar{BenzCar{"邁巴赫",99}})
    list = append(list,&FinanceBenzCar{BenzCar{"AMG",200}})
    list = append(list,&FinanceBenzCar{BenzCar{"V",40}})
    for _,v := range list {
        fmt.Println("車名:",v.GetName(),"\t價格:",v.GetPrice())
    }
 }
 copy</pre>

測試結果

<pre> === RUN   TestBenzCar_GetName
 車名: 邁巴赫     價格: 100
 車名: AMG     價格: 210
 車名: V     價格: 40
 --- PASS: TestBenzCar_GetName (0.00s)
 PASS
 copy</pre>

這樣,在業務規則發生改變的情況下,我們通過拓展子類及修改持久層(高層次模塊)便足以應對多變的需求。開閉原則要求我們儘可能通過拓展來實現變化,儘可能少地改變已有模塊,特別是底層模塊。

開閉原則總結:

  • 提高代碼復用性
  • 提高代碼的可維護性

本課不像其他項目實戰課程那般,相對晦澀難懂,不那麼富有趣味性,但任何一個有趣、有用的程式、項目或者游戲,都需要堅實的基本功方能實現,設計模式就是我們必學的基本功。

“每一棟大廈,都從一塊磚開始”


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1 分析: 2 需要動態的向資料庫中插入數據,既然要進行添加操作,就會觸發一個點擊的事件,所以我們的第一步就是要先綁定事件 3 向伺服器進行請求介面操作,請求的方法為 ‘POST’ 4 最後就是在methods中寫函數 5 操作: 6 (1)綁定事件 7 <view @tap="saveOpport ...
  • ECharts介紹 博客說明 文章所涉及的資料來自互聯網整理和個人總結,意在於個人學習和經驗彙總,如有什麼地方侵權,請聯繫本人刪除,謝謝! 說明 ECharts 是一個使用 JavaScript 實現的開源可視化庫,涵蓋各行業圖表,滿足各種需求 官網 https://echarts.apache.o ...
  • 大江東去,浪淘盡,千古風流人物。故壘西邊,人道是,三國周郎赤壁。亂石穿空,驚濤拍岸,捲起千堆雪。江山如畫,一時多少豪傑。遙想公瑾當年,小喬初嫁了,雄姿英發。羽扇綸巾,談笑間,檣櫓灰飛煙滅。故國神游,多情應笑我,早生華髮。人生如夢,一尊還酹江月。--來自奔跑的panda部落,panda每天與您一起進步 ...
  • 登高遠眺 滄海拾遺,積跬步以至千里 基礎技術 官宣: Typescript 3.9 正式發佈 TypeScript 3.9 正式發佈,這個版本主要聚焦於性能、改進某些特性和提升穩定性。編譯器效率在這一版有了極大提升,平均編譯時長從 26 秒縮短至 10 秒,改善了編輯體驗,同時修複了早期 Types ...
  • 首先前端三大件:前端的根本,html、css、JavaScript、JavaScript是重中之重。 庫工具:對於庫工具而言我們常用的有 JQuery、underScore、zepto、Moment 等 JQuery: 降低開發者操作 DOM 的複雜度 UnderScore: 提供實用的函數 Zep ...
  • 曾經某一刻,筆者也為下載離線地圖和載入地圖,煩惱過很久。在網上找了很多資料,都不全,不符合要求。要麼載入的百度、高德線上地圖;要麼就是沒有完整的離線地圖下載方式或者坐標體系對不上。搞了很久,也痛苦了很久,在這裡記錄一個完整的Demo。 離線地圖下載 以谷歌衛星地圖為例,下載某小區地圖。先用線條工具框 ...
  • 為什麼那麼多自學web前端的後來都放棄了,總結起來是這些原因 目前信息化產業發展勢頭很好,互聯網就成為了很多普通人想要涉及的行業,因為相比於傳統行業,互聯網行業漲薪幅度大,機會也多,所以就會有大批的人想要轉行從事這個行業,來學習web前端開發,目前來講市場上需要的web前端人員非常多,而且按照現在的 ...
  • 前提: (1) 相關博文地址: SpringBoot + Vue + ElementUI 實現後臺管理系統模板 -- 前端篇(一):搭建基本環境:https://www.cnblogs.com/l-y-h/p/12930895.html SpringBoot + Vue + ElementUI 實現 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...