跟著美團學設計模式(感處)

讀了著篇文章之后發現真的是,你的思想,你的思維是真的比比你擁有什么技術要強的。

注?

開閉原則

開閉原則(Open-Closed Principle)是面向對象設計中的基本原則之一,它的定義是:一個軟件實體應該對擴展開放,對修改關閉。也就是說,在軟件的生命周期內,當需要對軟件進行修改時,應該通過擴展軟件實體的行為來實現變化,而不是通過修改已有的代碼來實現變化。

開閉原則的目的是提高軟件的可復用性和可維護性。在軟件開發過程中,隨著業務需求的變化,軟件需求可能會發生變化,而開閉原則可以幫助我們避免對現有代碼的修改,從而減少引入新錯誤和重構整個功能的風險

迪米特法則

迪米特法則(Law of Demeter,LoD)是一種面向對象設計原則,也被稱為最少知識原則(Least Knowledge Principle,LKP)。它指出一個軟件實體應當盡可能少地與其他實體發生相互作用。如果一個系統符合迪米特法則,那么當其中某一個模塊發生修改時,就會盡量少地影響其他模塊,擴展會相對容易,這是對軟件實體之間通信的限制,迪米特法則要求限制軟件實體之間通信的寬度和深度。

迪米特法則的核心思想是降低組件之間的耦合度,提高代碼的松耦合性,從而使得代碼更易于維護、擴展和重構。在迪米特法則的指導下,一個類應該盡可能少地與其他類發生相互作用,盡量避免直接相互依賴,而是通過接口、抽象類等機制來進行通信,使得類與類之間的聯系更加松散,易于維護和擴展。

迪米特法則的命名來源于古希臘神話中的人物狄米特(Demeter),她是希臘神話中的農業女神,也是宙斯的姐姐。在這個神話中,狄米特規定了農業的生產規律,類似于迪米特法則規定了軟件實體之間的通信規律。

圍繞高內聚和低耦合兩個方面,然后結合設計模式

圍繞高內聚和低耦合兩個方面,然后結合設計模式

圍繞高內聚和低耦合兩個方面,然后結合設計模式

獎勵發放策略

第一天,老師問小明:“你知道活動營銷嗎?”
“這我知道,活動營銷是指企業通過參與社會關注度高的已有活動,或整合有效的資
源自主策劃大型活動,從而迅速提高企業及其品牌的知名度、美譽度和影響力,常見
的比如有抽獎、紅包等。”
老師點點頭:“是的。我們假設現在就要做一個營銷,需要用戶參與一個活動,然后完
成一系列的任務,最后可以得到一些獎勵作為回報。活動的獎勵包含美團外賣、酒旅
和美食等多種品類券,現在需要你幫忙設計一套獎勵發放方案。”
因為之前有過類似的開發經驗,拿到需求的小明二話不說開始了編寫起了代碼:

?小明很快寫好了 Demo,然后發給老師看。
“假如我們即將接入新的打車券,這是否意味著你必須要修改這部分代碼?”老師
問道。

一眼就看出了端詳。這不滿足我們設計原則中的開閉原則,和迪米特原則。

那我們該如何進行優化呢?

這個案例就可以用適配器和策略模式來調優

策略模式 | 菜鳥教程?? 適配器模式 | 菜鳥教程

先通過這個策略模式優化了變成如下代碼

?然后,小明創建策略模式的環境類,并供獎勵服務調用:

小明的代碼經過優化后,雖然結構和設計上比之前要復雜不少,但考慮到健壯性和拓展性,還是非常值得的。

策略類是有狀態的模型嗎?如果不是是否可以考慮做成單例的?

環境類的獲取策略方法職責很明確,但是依然沒有做到完全對修改封閉

解決 :可以將策略類單例化以減少開銷,并實現自注冊的功能徹底解決分支判斷

小明列出單例模式的要點:
單例模式? 設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。
這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被
創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該
類的對象。

?最終,小明在策略環境類中使用一個注冊表來記錄各個策略類的注冊信息,并提供接
口供策略類調用進行注冊。同時使用餓漢式單例模式去優化策略類的設計:

?

?

最終,小明設計完成的結構類圖如下:

如果使用了 Spring 框架,還可以利用 Spring 的 Bean 機制來代替上述的部分設計,
直接使用 @Component 和 @PostConstruct 注解即可完成單例的創建和注冊,代
碼會更加簡潔。

一些自己的思考

在設計你的業務邏輯的時候,或者寫你的邏輯的代碼,一定一定要思考設計模式-創造型模式,結構型模式,和行為型模式,還有下面的

J2EE 模式
這些設計模式特別關注表示層

我們該用什么。怎么調優

任務模型的設計

現在,我想讓你去完成任務模型的設計。你需要重點關注狀態的流轉變更,以及狀態變更后的消息通知。而上一個獎勵發放策略貌似是狀態的一個確定。

小明呢接下了難題,他首先定義了一套任務狀態的枚舉和行為的枚舉

然后,小明對開始編寫狀態變更功能

很明顯上述代碼 依然存在有上一個例子的問題。

問題是什么

第一,方法中使用條件判斷來控制語句,但是當條件復雜或者狀態太多時,條件判
斷語句會過于臃腫,可讀性差,且不具備擴展性,維護難度也大。且增加新的狀態時
要添加新的 if-else 語句,這違背了開閉原則,不利于程序的擴展

第二,任務類不夠高內聚,它在通知實現中感知了其他
領域或模塊的模型,如活動和任務管理器,這樣代碼的耦合度太高,不利于擴展

優化

首先是狀態流轉的控制可以使用狀態模式,其次,任務完成時的通知可以用到觀察者模式

觀察者模式 | 菜鳥教程 狀態模式 | 菜鳥教程

根據狀態模式的定義,小明將 TaskState 枚舉類擴展成多個狀態類,并具備完成狀
態的流轉的能力;然后優化了任務類的實現:

?小明欣喜地看到,經過狀態模式處理后的任務類的耦合度得到降低,符合開閉原則。
狀態模式的優點在于符合單一職責原則,狀態類職責明確,有利于程序的擴展。這樣設計的代價是狀態類的數目增加了,因此狀態流轉邏輯越復雜、需要處理的動作
越多,越有利于狀態模式的應用。

小明首先設計好抽象目標和抽象觀察者,然后將活動和任務管理器的接收通知功能定
制成具體觀察者:

?最后,小明將任務進行狀態類優化成使用通用的通知方法,并在任務初始態執行狀態
流轉時定義任務進行態所需的觀察者

?

最終,小明設計完成的結構類圖如下

?通過觀察者模式,小明讓任務狀態和通知方實現松耦合(實際上觀察者模式還沒能做到完全的解耦,如果要做進一步的解耦可以考慮學習并使用發布 - 訂閱模式)

活動的迭代重構

活動模型的特點在于其組成部分較多,小明原先的活動模型的構建方式是這樣的

?

上述代碼得問題主要表現在

活動的構造組件較多,導致可以組合的構造函數太多,尤其是在模型增加字段時還需
要去修改構造函數

部分組件的構造存在一定的順序關系,但是當前的實現沒有體現順序,導致構造邏輯
比較混亂,并且存在部分重復的代碼

這種情況呢?我們使用創建者模式。

在實際的應用中,如果字段類型多,
同時各個字段只需要簡單的賦值,可以直接引用 Lombok 的 @Builder 注解來實現
輕量的建造者。

重構完活動構建的設計后,小明開始對參加活動方法增加風控。最簡單的方式肯定是

直接修改目標方法。但是是有的活動需要風控有的不需要。這時候我們就用了裝飾者模式。來進行風控。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/43168.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/43168.shtml
英文地址,請注明出處:http://en.pswp.cn/news/43168.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python生成旗幟--比如美國國旗生成

目錄 1、解釋說明: 2、使用示例: 3、注意事項: 1、解釋說明: 在Python中,生成國旗可以通過使用第三方庫或者自定義函數來實現。通常,我們可以使用Pillow庫來處理圖像,以及使用matplotlib庫來…

python爬蟲7:實戰1

python爬蟲7:實戰1 前言 ? python實現網絡爬蟲非常簡單,只需要掌握一定的基礎知識和一定的庫使用技巧即可。本系列目標旨在梳理相關知識點,方便以后復習。 申明 ? 本系列所涉及的代碼僅用于個人研究與討論,并不會對網站產生不好…

carla中lka實現(二)

前言: 首先計算之前檢測出來的車道線的中線與輸入圖像的中線進行計算距離,,并設置不同的閾值對于不同的方向進行相關的調整。 一、車輛中心線 一般而言將攝像頭架設在車輛的正中心軸上,所獲得的圖像的中間線極為車輛的中心。 …

QGraphicsView 實例3地圖瀏覽器

主要介紹Graphics View框架&#xff0c;實現地圖的瀏覽、放大、縮小&#xff0c;以及顯示各個位置的視圖、場景和地圖坐標 效果圖: mapwidget.h #ifndef MAPWIDGET_H #define MAPWIDGET_H #include <QLabel> #include <QMouseEvent> #include <QGraphicsView&…

WSL2 ubuntu子系統OpenCV調用本機攝像頭的RTSP視頻流做開發測試

文章目錄 前言一、Ubuntu安裝opencv庫二、啟動 Windows 本機的 RTSP 視頻流下載解壓 EasyDarwin查看本機攝像頭設備開始推流 三、在ubuntu 終端編寫代碼創建目錄及文件創建CMakeLists.txt文件啟動 cmake 配置并構建 四、結果展示啟動圖形界面在圖形界面打開終端找到 rtsp_demo運…

linux系統服務學習(二)linux下yum源配置實戰

文章目錄 Linux下yum源配置實戰一、Linux下軟件包的管理1、軟件安裝方式2、源碼安裝的配置過程3、詳解源碼安裝的配置過程&#xff08;定制&#xff09;4、詳解編譯過程5、安裝過程6、axel多線程下載軟件源碼安裝7、使用軟鏈接解決command not found8、使用環境變量解決command…

軟考A計劃-系統集成項目管理工程師-收尾管理

點擊跳轉專欄>Unity3D特效百例點擊跳轉專欄>案例項目實戰源碼點擊跳轉專欄>游戲腳本-輔助自動化點擊跳轉專欄>Android控件全解手冊點擊跳轉專欄>Scratch編程案例點擊跳轉>軟考全系列點擊跳轉>藍橋系列 &#x1f449;關于作者 專注于Android/Unity和各種游…

字符串的無重復排列組合

題目描述&#xff1a; 無重復字符串的排列組合。編寫一種方法&#xff0c;計算某字符串的所有排列組合&#xff0c;字符串每個字符均不相同。 示例1: 輸入&#xff1a;S "qwe" 輸出&#xff1a;["qwe", "qew", "wqe", "weq&q…

中間件(二)dubbo負載均衡介紹

一、負載均衡概述 支持輪詢、隨機、一致性hash和最小活躍數等。 1、輪詢 ① sequences&#xff1a;內部的序列計數器 ② 服務器接口方法權重一樣&#xff1a;&#xff08;sequences1&#xff09;%服務器的數量&#xff08;決定調用&#xff09;哪個服務器的服務。 ③ 服務器…

opencv直方圖與模板匹配

import cv2 #opencv讀取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 直方圖 cv2.calcHist(images,channels,mask,histSize,ran…

Spring中Bean的生命周期以及Bean的單例與多例模式

一. Bean的生命周期 bean的生命周期可以表達為&#xff1a;bean的定義?bean的初始化?bean的使用?bean的銷毀 Bean的初始化過程 1&#xff09;通過XML、Java annotation&#xff08;注解&#xff09;以及Java Configuration&#xff08;配置類&#xff09; 等方式加載Bea…

2023+HuggingGPT: Solving AI Tasks with ChatGPT and itsFriends in Hugging Face

摘要&#xff1a; 語言是llm(例如ChatGPT)連接眾多AI模型(例如hugs Face)的接口&#xff0c;用于解決復雜的AI任務。在這個概念中&#xff0c;llms作為一個控制器&#xff0c;管理和組織專家模型的合作。LLM首先根據用戶請求規劃任務列表&#xff0c;然后為每個任務分配專家模…

Unity 鼠標實現對物體的移動、縮放、旋轉

文章目錄 1. 代碼2. 測試場景 1. 代碼 using UnityEngine;public class ObjectManipulation : MonoBehaviour {// 縮放比例限制public float MinScale 0.2f;public float MaxScale 3.0f;// 縮放速率private float scaleRate 1f;// 新尺寸private float newScale;// 射線pri…

【Windows系統編程】03.遠線程注入ShellCode

shellcode&#xff1a;本質上也是一段普通的代碼&#xff0c;只不過特殊的編程手法&#xff0c;可以在任意環境下&#xff0c;不依賴于原有的依賴庫執行。 遠程線程 #include <iostream> #include <windows.h> #include <TlHelp32.h>int main(){HANDLE hPr…

Educational Codeforces Round 153 (Rated for Div. 2)ABC

Educational Codeforces Round 153 (Rated for Div. 2) 目錄 A. Not a Substring題目大意思路核心代碼 B. Fancy Coins題目大意思想核心代碼 C. Game on Permutation題目大意思想核心代碼 A. Not a Substring 題目大意 給定一個只包含“&#xff08;”和“&#xff09;”這兩…

react-native-webview RN和html雙向通信

rn登錄后得到的token需要傳遞給網頁&#xff0c;js獲取到的瀏覽器信息需要傳遞給rn RN Index.js: import React from react import { WebView } from react-native-webview import useList from ./useListexport default function Index(props) {const { uri, jsCode, webVie…

iPhone刪除的照片能恢復嗎?不小心誤刪了照片怎么找回?

iPhone最近刪除清空了照片還能恢復嗎&#xff1f;大家都知道&#xff0c;照片對于我們來說是承載著美好回憶的一種形式。它記錄著我們的平淡生活&#xff0c;也留住了我們的美好瞬間&#xff0c;具有極其重要的紀念價值。 照片不小心誤刪是一件非常難受的事&#xff0c;那么iP…

android TextView 超出長度使用省略號

在Android中最常見的需求&#xff0c;就是在在外部展示信息時&#xff0c;需要簡要展示內容。TextView僅需在靜態布局文件中設置以下幾個屬性&#xff1a; android:maxWidth“100dp” // 寬度是多少才算超出 android:maxLines"2" // 高度多少才算超出 android:elli…

React下載文件的兩種方式

React下載文件的兩種方式 - 代碼先鋒網 不知道有用沒用看著挺整齊 沒試過 1、GET類型下載 download url > {const eleLink document.createElement(a);eleLink.style.display none;// eleLink.target "_blank"eleLink.href url;// eleLink.href record;d…

Centos7 配置Docker鏡像加速器

docker實戰(一):centos7 yum安裝docker docker實戰(二):基礎命令篇 docker實戰(三):docker網絡模式(超詳細) docker實戰(四):docker架構原理 docker實戰(五):docker鏡像及倉庫配置 docker實戰(六):docker 網絡及數據卷設置 docker實戰(七):docker 性質及版本選擇 認知升…