設計模式學習筆記(一)

設計模式學習筆記(一)

一般說設計模式都是指面向對象的設計模式,因為面向對象語言可以借助封裝、繼承、多態等特性更好的達到復用性、可拓展性、可維護性。

面向對象一般指以類、對象為組織代碼的基本單元,并將封裝、繼承、多態、抽象四個特性(抽象有的定義里并不認為是四大特性)作為代碼設計與實現的基石。

  • 封裝:通過訪問權限控制,只對外暴露必要的操作,保護數據。

  • 繼承:代碼復用,結構美感。不過 Java 語言不支持多重繼承,原因是如果 BC 都繼承了 A 并重寫了某個方法,D 同時繼承 BC 會產生歧義。

  • 多態:提高代碼的復用性,主要通過兩種方式實現

    • 繼承:父類引用指向子類對象
    • 實現:接口引用指向具體實現類
  • 抽象:有時并不計入四大特性,用來保護實現,例如接口就是對實現的一種抽象,無需關注實現

有些設計看似是面向對象

  • 濫用 getter、setter 方法。lombok 的注解確實很方便,但這樣其實違背了面向對象的封裝特性,例如 createTime 等字段其實是不需要 setter 方法的,需要在創建對象的時候就確定。
  • 濫用全局變量、全局方法(Constants、Utils)。這樣會導致修改后所有引用的地方都重新編譯,而且有的時候只需要其中的某幾個變量(或方法)卻導入了整個類。
    • 功能拆分,不要定義一個大而全的類。例如 Constants 拆分為 DateConstants、RedisConstants、MysqlConstants
  • 定義數據與方法分離的類。傳統的 MVC 開發中,數據在相應的 BO、VO、PO 中,而操作卻封裝在對應的 Controller、Service 中,這就是典型的面向過程,也就是“貧血模型”的開發方法。不過這樣的開發方式依然很流行,因為大部分的需求并不復雜,甚至只是從數據庫中找到查哪些字段,組織對應的 VO,先寫 service 反推 controller。

如何理解接口與抽象類

隨著 jdk 版本的更新,接口也可以有默認實現,也可以定義變量作為常量使用。抽象類依然不允許被實例化,繼承抽象類必須重寫抽象類的所有方法。

先說結論:抽象類的作用更多是為了代碼復用,而接口的作用則更偏向與“協議”,具備什么樣的功能。

public class BaseEntity implements Serializable {private static final long serialVersionUID = 8417380540303280008L;@ApiModelProperty(value = "所屬用戶標識")@Column(name = "USER_ID")private String userId;@ApiModelProperty(value = "記錄是否有效,默認為1表示有效")@Column(name = "ACTIVE")private String active;@ApiModelProperty(value = "創建時間,默認為當前時間")@Column(name = "CREATED_AT", updatable = false)@DateTimeFormat(pattern = Constants.PATTERN_DATE_HOUR_MINUTE_SECOND)@JsonFormat(pattern = Constants.PATTERN_DATE_HOUR_MINUTE_SECOND, timezone = Constants.TIMEZONE)private Date createdAt;@ApiModelProperty(value = "更新時間")@Column(name = "UPDATED_AT")@DateTimeFormat(pattern = Constants.PATTERN_DATE_HOUR_MINUTE_SECOND)@JsonFormat(pattern = Constants.PATTERN_DATE_HOUR_MINUTE_SECOND, timezone = Constants.TIMEZONE)private Date updatedAt;}

例如我們有一個上面的類,對于一個正常的刪除來講,一方面我們要查詢這個數據是否存在(例如有些系統刪除不存在的空數據會返回錯誤),另一方面判斷當前登錄用戶是否具有刪除權限(即資源的 USER_ID 是否為當前登錄人或是否是當前登錄人的下屬),最后還需要記錄日志。

public void delete(String uuid) {Entity entity = getEntityFromDB(uuid);if (entity == null) {throw ......}if (entity instanceof BaseEntity) {BaseEntity e = (BaseEntity)entity;if (!e.getActive.equals("1")) {} else {e.setActive("0");saveEntityToDB(entity);}}
}protected abstract T saveToDataBase(T entity);protected abstract Entity getEntityFromDB(String uuid);

借助抽象類與多態,可以提高代碼的復用性,減少重復代碼。

如何理解基于接口而非實現編程

假如目前有一個上傳圖片到公有云的需求

public class uploadPictureAliyunImpl {// 獲取合法 tokenpublic String getToken() {};// 如果目錄不存在就創建目錄public boolean createDictoryIfNotExists() {};// 上傳圖片public boolean uploadPictureToAliyun() {};}public class Main() {public static void Main () {uploadPictureAliyunImpl impl = new uploadPictureAliyunImpl();String token = impl.getToken();........}
}

如果這樣實現,后期替換為其他云廠商,例如自有的私有云,就需要替換很多代碼,實際上這種情況只需要定義一個上傳圖片的接口,由不同的存儲來實現就行。

基于接口編程,即進行更好的抽象設計,不暴露過多實現。

為什么說多用組合少用繼承

以鳥(bird)為例,可以分為是否會飛、是否會下蛋…

image-20250916170508725

當繼承層次越來越深,關系會越來越復雜,會嚴重影響代碼的穩定性與可維護性。但是當繼承層次很淺且業務穩定時,依然可以利用繼承和多態特性來實現特定功能。

繼承實際上可以替換為組合來實現,例如定義兩個接口:

public interface Flyable {void fly();
}public interface Eggable {void egg();
}

每一種鳥類根據自己的情況來實現對應接口即可,但是這會引入新的問題,例如有 n 個鳥類實現的 fly 接口都是一樣的,那代碼重復會十分嚴重,解決方式就是“委托”:

public class DefaultFlyableImpl implements Flyable {void fly() {......}
}public class AAABird implements Flyable {// 其實一般是使用注解注入private DefaultFlyableImpl defaultFlyImpl = new DefaultFlyableImpl();void fly() {defaultFlyImpl.fly();}}

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

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

相關文章

【CSS】一個自適應大小的父元素,如何讓子元素的寬高比一直是2:1

父元素是自適應大小的容器(比如 width:100%),我們希望子元素 始終保持 2:1 寬高比(比如寬 200px → 高 100px,寬 300px → 高 150px)。 有幾種常見解法:? 方法一:CSS aspect-ratio&…

如何搭建redis集群(docker方式非哨兵)

1、redis的配置文件這里要注意,主從的ip不需要我們去設置,只需要設置主從的密碼就可以,然后就是protect-mode,我設置的是no,一定注意不能設置主從。客戶端要訪問,一定要加# 每個節點的 redis.conf 中 clust…

如何學習VBA_3.3.9:利用“搭積木”思想,快速有效地完成你的代碼

我給VBA的定義:VBA是個人小型自動化處理的有效工具。利用好了,可以大大提高自己的勞動效率,而且可以提高數據處理的準確度。我推出的VBA系列教程共九套和一部VBA漢英手冊,現在已經全部完成,希望大家利用、學習。如果您…

JSP程序設計之輸入/輸出對象 — response對象

response對象1.概述2.實例:response對象方法運用(1)實例一:頁面自動刷新(2)實例二:實現頁面重定向,具體的代碼(3)綜合實例:實現登錄并記錄用戶名1…

Redis 事件驅動框架(ae.c_ae.h)深度解析

Redis 事件驅動框架(ae.c/ae.h)深度解析 之前咱們用 “超市收銀員” 的例子,簡單看懂了 ae 模塊是 Redis 的 “多任務神器”。現在咱們再往深走一層,不用復雜代碼,只拆它的 “核心運作邏輯”—— 搞懂它怎么做到 “一個…

[能源化工] 面向鋰電池RUL預測的開源項目全景速覽

鋰離子電池是新能源汽車、儲能系統及便攜式電子設備的核心能源部件,其剩余使用壽命(Remaining Useful Life,RUL)的準確預測直接關系到設備運行安全、維護成本優化和能源效率提升。RUL預測算法能夠提前量化電池剩余可用時間&#x…

PEFT QLora Deepspeed Zero Stage 3 Offload Trainning

使用 accelerate deepspeed zero stage 3 offload 進行 sft trainning 的自動設備映射: GPU 訓練計算 CPU 存儲 run_peft_qlora_deepspeed_stage3.sh #!/bin/bashexport MAX_JOBS4 export OMP_NUM_THREADS4 export disable_exllamaTrue export CUDA_VISIBLE_DEVICES0,1 expor…

JAVA上門家政維修服務系統源碼微信小程序+微信公眾號+APP+H5

一、功能介紹用戶端:精準分類、支持家政、維修、萬能服務、一口價、報價、線上、各類家政服務、優惠專區、師傅入駐、商家入駐、我的需求、補費明細、我的投訴;師傅端:接單池、消息通知、接單管理、今日訂單、師傅入駐、我的錢包、實名認證&a…

GCKontrol對嵌入式設備FPGA設計流程的高效優化

1 前言FPGA(Field-Programmable Gate Array,現場可編程邏輯門陣列)是一種可編程的半導體器件,因其硬件可重構性、硬件并行計算能力、低延遲和實時性的優勢,廣泛應用于數字電路設計、原型驗證和系統加速等領域。但開發…

DBAPI免費版對比apiSQL免費版

DBAPI簡介 零代碼開發api服務,只需編寫sql,就可以生成http api服務。支持api動態創建,兼容多種數據庫。 適用于BI報表、數據可視化大屏的后端接口快速開發。 旨在為企業數據服務的發布提供完整解決方案 一、DBAPI免費版本支持1個數據源連接支…

CTFHub SSRF通關筆記8:數字IP Bypass 原理詳解與滲透實戰

目錄 一、SSRF 二、數字IP原理 1、IP多進制 (1)十進制整數格式 (Dword / 長整數格式) (2)八進制格式 (Octal IP) (3)十六進制格式 (Hex IP) 2、SSRF繞過 三、滲透實戰 1、打開靶場 2、嘗試127.0.…

C++中雙引號和單引號的區別(全面分析)

我在刷算法題的時候經常遇到,用了 出現警告或者使用" "直接報錯,尤其是在字符串部分(py玩家后遺癥/(ㄒoㄒ)/~~)在詳細了解后總結一下加強記憶。 總的來說在 C 中,雙引號 "" 和單引號 是完全不同…

Ubuntu20.04仿真 |iris四旋翼添加云臺相機詳述

申明: 1、本人使用的是Ubuntu20.04ros1gazeboxtdronepx4的仿真組合 2、為了使傳感器模型和飛機模型解耦合,實現不同平臺對傳感器可直接調用,本系列博文涉及的所有傳感器均不直接添加在相應平臺的sdf當中,而是通過編寫xxx_joint.…

《人工智能AI之機器學習基石》系列 第 16 篇:關聯規則與數據挖掘——“啤酒與尿布”傳奇背后的增長秘密

《人工智能AI之機器學習基石》? 專欄核心理念: 用通俗語言講清楚機器學習的核心原理,強調“洞察+ 技術理解 + 應用連接”,構建一個完整的、富有啟發性的知識體系。 引言:藏在購物車里的“讀心術” 朋友們,歡迎回到我們的AI基石之旅。 在過去的兩次探索中,我們深入…

Spring Boot 的自動配置原理

Spring Boot 的自動配置是其 "約定大于配置" 理念的核心實現,它能自動配置 Spring 應用所需的各種組件,大幅減少手動配置。下面從核心注解、加載流程、條件過濾等方面詳細講解其原理,并結合關鍵源碼說明。一、自動配置的入口&#…

谷歌云平臺(Google Cloud Platform, GCP)介紹(全球領先的云計算服務平臺,為企業和開發者提供包括計算、存儲、數據分析、人工智能、機器學習、網絡和安全等在內的全面云服務)

文章目錄**1. GCP的核心優勢****1.1 全球領先的基礎設施****1.2 強大的數據分析和人工智能能力****1.3 卓越的安全性和合規性****1.4 靈活的定價模式****2. GCP的主要服務****2.1 計算服務****2.2 存儲和數據庫****2.3 網絡服務****2.4 人工智能與大數據****2.5 安全與管理工具…

RISC-V異常機制和異常定位

不少人在調試RISC-V core時,面對異常的出現不知所措,不知道如何定位代碼問題。這里將從RISC-V異常機制以及幾個異常實例學習下。 1 異常機制 1.1 什么是異常 異常是軟件程序員不得不要深入了解的,首先在學習異常機制前,對異常要…

c++中導出函數調用約定為__stdcall類型函數并指定導出函數名稱

開發環境在Visual studio 2022版本下,為防止編譯器重命名函數名稱(會加上8等等亂七八糟的東西),我們對函數名稱進行指定:一、新建.def文件,名稱須與dll名稱相同,并放在與cpp文件相同文件夾下&am…

Vision Transformer (ViT) :Transformer在computer vision領域的應用(二)

METHOD,論文主要部分 In model design we follow the original Transformer (Vaswani et al., 2017) as closely as possible. An advantage of this intentionally simple setup is that scalable NLP Transformer architectures – and their efficient implementations –…

AI 論文周報丨紅隊測試語言模型/多視角 3D 點追蹤方法/蛋白質表示學習框架/密碼學漏洞檢測新框架……

近年來,已有若干方法嘗試從單目視頻實現 3D 點跟蹤,然而由于在遮擋和復雜運動等挑戰性場景中難以準確估計 3D 信息,這些方法的性能仍難以滿足實際應用對高精度與魯棒性的要求。 基于此,蘇黎世聯邦理工學院、卡內基梅隆大學聯合提出…