設計模式和單一原則筆記

單一原則:方法 對象

策略模式:方法實現

// 策略接口(單一職責:定義計算規范)
public interface PriceStrategy {boolean match(String type);  // 職責1:判斷是否適用該策略double calculate(double price); // 職責2:執行計算
}// 具體策略類(每個類只負責一種計算邏輯)
public class VipStrategy implements PriceStrategy {@Overridepublic boolean match(String type) {return "VIP".equals(type);}@Overridepublic double calculate(double price) {return price * 0.8;}
}public class FullReductionStrategy implements PriceStrategy {@Overridepublic boolean match(String type) {return "FULL_REDUCTION".equals(type);}@Overridepublic double calculate(double price) {return price > 100 ? price - 20 : price;}
}// 上下文類(單一職責:路由策略)
public class PriceContext {private List<PriceStrategy> strategies = new ArrayList<>();public PriceContext() {strategies.add(new VipStrategy());strategies.add(new FullReductionStrategy());}public double execute(String type, double price) {return strategies.stream().filter(s -> s.match(type)).findFirst().orElseThrow(() -> new IllegalArgumentException("未知價格策略")).calculate(price);}
}

** 使用工廠模式隔離對象創建**

// 創建邏輯單獨封裝
public class PaymentProcessorFactory {public PaymentProcessor create(String type) {if ("ALIPAY".equals(type)) return new AlipayProcessor();if ("WECHAT".equals(type)) return new WechatProcessor();throw new IllegalArgumentException("未知支付類型");}
}// 使用方保持單一職責
public class OrderService {private PaymentProcessorFactory factory;public void pay(Order order, String paymentType) {PaymentProcessor processor = factory.create(paymentType);processor.process(order.getAmount());}
}

通過裝飾者模式疊加功能

// 基礎接口
public interface DataReader {String read();
}// 基礎實現(單一職責:讀取數據)
public class FileDataReader implements DataReader {public String read() {// 讀取文件內容...}
}// 裝飾器1:增加緩存(單一職責:處理緩存)
public class CachedDataReader implements DataReader {private DataReader wrappee;private String cache;public CachedDataReader(DataReader reader) {this.wrappee = reader;}public String read() {if (cache == null) {cache = wrappee.read();}return cache;}
}// 裝飾器2:增加解密(單一職責:數據解密)
public class DecryptDataReader implements DataReader {private DataReader wrappee;public DecryptDataReader(DataReader reader) {this.wrappee = reader;}public String read() {String data = wrappee.read();return decrypt(data);}
}// 使用組合
DataReader reader = new DecryptDataReader(new CachedDataReader(new FileDataReader()));

1 工廠方法模式(子類創建對象 接口屏蔽細節 支持新增產品)

抽象工廠1接口,具體工廠AB實現接口方法,
服務類 1 factory; if (…) {factory = new FactoryA();} factory調用方法

適用場景:需要創建對象但不確定具體類型時(如多數據源切換、協議適配)。
特點

  • 將對象創建延遲到子類
  • 通過接口屏蔽創建細節
  • 支持橫向擴展(新增產品類型)

微服務應用示例:多數據庫支持(MySQL/Oracle)

// 抽象工廠
public interface DataSourceFactory {DataSource createDataSource();
}// 具體工廠
public class MySQLDataSourceFactory implements DataSourceFactory {@Overridepublic DataSource createDataSource() {MysqlDataSource dataSource = new MysqlDataSource();dataSource.setURL("jdbc:mysql://localhost:3306/db");return dataSource;}
}public class OracleDataSourceFactory implements DataSourceFactory {@Overridepublic DataSource createDataSource() {OracleDataSource dataSource = new OracleDataSource();dataSource.setURL("jdbc:oracle:thin:@localhost:1521:xe");return dataSource;}
}// 使用工廠(通過環境變量切換)
public class DatabaseService {private DataSource dataSource;public DatabaseService() {String dbType = System.getenv("DB_TYPE");DataSourceFactory factory;if ("oracle".equalsIgnoreCase(dbType)) {factory = new OracleDataSourceFactory();} else {factory = new MySQLDataSourceFactory();}this.dataSource = factory.createDataSource();}
}

2 抽象工廠模式(定義抽象產品和工廠并實現,產品不能不太多)

創建工廠A 抽象產品BC 實現A和BC 選擇工廠

1. 模式定義
抽象工廠模式是一種創建型設計模式,它提供一個接口用于創建相關或依賴對象的家族,而無需指定具體類。與工廠方法模式不同,抽象工廠關注的是產品族的創建。

核心思想:客戶端代碼只與抽象接口交互,完全不知道實際創建的具體產品是什么。

2. 模式結構
角色劃分

角色說明示例代碼
AbstractFactory(抽象工廠)聲明創建產品族的方法GUIFactory
ConcreteFactory(具體工廠)實現具體產品的創建WindowsFactory/MacFactory
AbstractProduct(抽象產品)定義產品接口Button/Checkbox
ConcreteProduct(具體產品)實現具體產品類WindowsButton/MacCheckbox

UML類圖
在這里插入圖片描述

3. 代碼示例:跨平臺UI組件庫

場景需求
開發一個支持Windows和Mac風格的UI庫,需要創建:

  • 按鈕(Button)
  • 復選框(Checkbox)

(1)抽象產品定義

// 抽象產品:按鈕
public interface Button {void render();void onClick();
}// 抽象產品:復選框
public interface Checkbox {void paint();boolean isChecked();
}

(2)具體產品實現

// Windows風格組件
public class WindowsButton implements Button {@Overridepublic void render() {System.out.println("渲染Windows風格按鈕");}@Overridepublic void onClick() {System.out.println("Windows按鈕點擊事件");}
}public class WindowsCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("繪制Windows風格復選框");}@Overridepublic boolean isChecked() {return true;}
}// Mac風格組件
public class MacButton implements Button {@Overridepublic void render() {System.out.println("渲染Mac風格按鈕");}@Overridepublic void onClick() {System.out.println("Mac按鈕點擊事件");}
}public class MacCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("繪制Mac風格復選框");}@Overridepublic boolean isChecked() {return false;}
}

(3)抽象工廠定義

public interface GUIFactory {Button createButton();Checkbox createCheckbox();
}

(4)具體工廠實現

// Windows工廠
public class WindowsFactory implements GUIFactory {@Overridepublic Button createButton() {return new WindowsButton();}@Overridepublic Checkbox createCheckbox() {return new WindowsCheckbox();}
}// Mac工廠
public class MacFactory implements GUIFactory {@Overridepublic Button createButton() {return new MacButton();}@Overridepublic Checkbox createCheckbox() {return new MacCheckbox();}
}

(5)客戶端代碼

public class Application {private Button button;private Checkbox checkbox;public Application(GUIFactory factory) {this.button = factory.createButton();this.checkbox = factory.createCheckbox();}public void paint() {button.render();checkbox.paint();}public static void main(String[] args) {// 根據配置選擇工廠GUIFactory factory;if (System.getProperty("os.name").contains("Windows")) {factory = new WindowsFactory();} else {factory = new MacFactory();}Application app = new Application(factory);app.paint();}
}

4. 模式優勢

優點

  1. 確保產品兼容性:同一工廠創建的對象屬于同一產品族
  2. 客戶端與具體實現解耦:只依賴抽象接口
  3. 易于擴展新產品族:新增風格只需增加新工廠類

缺點

  1. 增加新產品類型困難:需要修改所有工廠接口(違反開閉原則)
  2. 類數量膨脹:每增加一個產品族需要新增多個類

5. 經典應用場景

  1. 跨平臺UI框架(如Java AWT/Swing)
  2. 數據庫訪問層(支持多種數據庫:MySQL/Oracle)
  3. 游戲開發(不同風格的角色/道具生成)
  4. 主題系統(白天/黑夜模式切換)

6. 模式對比
(1)抽象工廠 vs 工廠方法

維度抽象工廠工廠方法
關注點產品族創建單一產品創建
復雜度高(需要管理多個產品等級)
擴展方向橫向擴展(新增產品族)縱向擴展(新增產品類型)
(2)抽象工廠 vs 建造者模式
  • 抽象工廠:立即返回組成產品族的各個對象
  • 建造者:分步驟構建復雜單一對象

7. Spring框架中的實踐

Spring的FactoryBean接口與抽象工廠模式思想相似:

public interface FactoryBean<T> {T getObject() throws Exception;  // 相當于createProduct()Class<?> getObjectType();boolean isSingleton();
}// 使用示例
@Bean
public FactoryBean<DataSource> dataSource() {return new AbstractFactoryBean<DataSource>() {@Overridepublic Class<?> getObjectType() {return DataSource.class;}@Overrideprotected DataSource createInstance() {// 返回具體數據源實現return new HikariDataSource();}};
}

8. 最佳實踐建議

  1. 合理控制產品族規模:避免一個工廠需要創建過多產品
  2. 考慮使用依賴注入(如Spring)來管理工廠實例
  3. 與原型模式結合:當產品創建成本高時,可以用原型減少new操作
  4. 明確產品族邊界:不同產品族之間不應有隱含依賴

3 模板(代碼少 父類掌握流程 有鉤子)


抽象類 靜態方法寫步驟1234,拆分具體步驟,固定/抽象/鉤子都行

經典案例
1. Java 集合框架
- AbstractListaddAll() 方法調用 add()(子類如 ArrayList 實現 add())。
2. Servlet 生命周期
- HttpServletservice() 方法調用 doGet()doPost()
3. Sp ring 框架
- JdbcTemplateexecute() 方法定義數據庫操作流程,具體 SQL 由回調接口實現。

public abstract class AbstractClass {// 模板方法(final防止子類覆蓋算法結構)public final void templateMethod() {step1();     // 固定步驟step2();     // 可變步驟(子類實現)if (hookMethod()) {  // 鉤子方法(可選擴展點)step3();  }}// 固定實現(所有子類共用)private void step1() {System.out.println("執行固定步驟1");}// 抽象方法(必須由子類實現)protected abstract void step2();// 鉤子方法(可選覆蓋,提供默認實現)protected boolean hookMethod() {return true;}// 可選步驟(默認空實現)protected void step3() {}}

優勢

  • 代碼復用:公共邏輯集中在父類
  • 擴展可控:通過鉤子方法提供靈活擴展點
  • 反向控制:父類掌控流程,子類專注實現

劣勢

  • 繼承強耦合:子類必須依賴父類
  • 違反開閉原則:新增步驟可能需要修改父類
  • 方法爆炸:過多抽象方法會增加子類負擔

建議

  1. 模板方法盡量簡短(不超過10行)
  2. 命名顯式化
    • 模板方法用processXXX()/executeXXX()
    • 步驟方法用doXXX()/performXXX()
  3. 謹慎使用繼承:如果變化點過多,考慮改用策略模式
  4. 合理使用鉤子方法:避免過度設計,只在真正需要擴展點時使用

4 策略模式 (新增不用改舊代碼 支付)

模式優勢
優點
開閉原則:新增策略無需修改現有代碼
消除條件語句:替代大量的if-else/switch-case
運行時靈活切換:動態改變對象行為
算法復用:不同上下文可共享策略對象

缺點
客戶端必須了解所有策略:需要知道不同策略的區別
對象數量增加:每個策略都是一個類
通信開銷:策略與上下文可能需要交換數據

經典應用場景
支付系統(如示例)
排序算法(快速排序/歸并排序動態切換)
游戲AI(不同難度級別的敵人行為)
物流計算(不同快遞公司的運費計算)
Spring資源訪問Resource接口的不同實現)

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

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

相關文章

常見正則表達式整理與Java使用正則表達式的例子

一、常見正則表達式整理 1. 基礎驗證類 郵箱地址 ^[a-zA-Z0-9._%-][a-zA-Z0-9.-]\\.[a-zA-Z]{2,}$ &#xff08;匹配如 userexample.com&#xff09;手機號 ^1[3-9]\\\\d{9}$ &#xff08;匹配國內11位手機號&#xff0c;如 13812345678&#xff09;中文字符 ^[\u4e00-\u9fa5…

vue2 項目的 vscode 插件整理

Folder Selector 當項目文件很多時&#xff0c;查找一個文件&#xff0c;可能需要在資源管理器中不斷的滾動再打開文件夾查找文件&#xff0c;很麻煩&#xff0c;這個可以增加一個面板通過右鍵文件夾選擇 然后在面板中查看文件 Reveal Button 文件中跳轉到另一個文件時&#…

使用 Node、Express 和 MongoDB 構建一個項目工程

本文將詳細介紹如何使用 Node.js Express MongoDB 構建一個完整的 RESTful API 后端項目&#xff0c;涵蓋&#xff1a; 項目初始化 Express 服務器搭建 MongoDB 數據庫連接 REST API 設計&#xff08;CRUD 操作&#xff09; 錯誤處理與中間件 源碼結構與完整代碼 部署建…

如何實現Spring Boot應用程序的安全性:全面指南

在現代 Web 開發中&#xff0c;安全性是 Spring Boot 應用程序的核心需求&#xff0c;尤其是在微服務、云原生和公開 API 場景中。Spring Boot 結合 Spring Security 提供了一套強大的工具&#xff0c;用于保護應用程序免受常見威脅&#xff0c;如未經授權的訪問、數據泄露、跨…

無人機避障——Mid360+Fast-lio感知建圖+Ego-planner運動規劃(胎教級教程)

電腦配置:Xavier-nx、ubuntu 18.04、ros melodic 激光雷達:Livox_Mid-360 結果展示:左邊Mid360+Fast-lio感知建圖,右邊Ego-planner運動規劃 1、讀取雷達數據并顯示 無人機避障——感知篇(采用Livox-Mid360激光雷達獲取點云數據顯示)-CSDN博客 看看雷達數據話題imu以及…

數據庫證書可以選OCP認證嗎?

直接回答&#xff1a;國內OCP認證持有者的年薪普遍在15萬到40萬元之間&#xff0c;具體收入與經驗、地區和行業強相關。OCP認證能大幅提升求職競爭力&#xff0c;但薪資天花板仍由個人能力決定。 一、薪資范圍和核心影響因素 OCP認證是Oracle數據庫領域的中高級“技術通行證”…

MySQL 從入門到精通:第二篇 - 數據類型、約束與索引

1. MySQL數據類型詳解 數值類型 整數類型 -- 常用整數類型及范圍 CREATE TABLE integer_types (tiny_col TINYINT, -- 1字節,有符號(-128~127),無符號(0~255)small_col SMALLINT, -- 2字節,有符號(-32768~32767),無符號(0~65535)medium_col MEDIUMINT,

Arduino 入門學習筆記(二):開發環境搭建

Arduino 入門學習筆記&#xff08;二&#xff09;&#xff1a;開發環境搭建 B站學習鏈接&#xff1a;link 1. Arduino IDE2軟件介紹 Arduino IDE&#xff0c;Arduino Integrated Development Environment&#xff0c;即Arduino集成開發環境。 Arduino IDE具有程序編輯、調試…

ChatGPT、deepseek、豆包、Kimi、通義千問、騰訊元寶、文心一言、智譜清言代碼能力對比

均使用測試時的最強模型 均是一次對話,對話內容一樣 均開啟深度思考 能聯網的都聯網了&#xff0c;但是作用不大&#xff0c;因為藍橋杯剛考完&#xff0c;洛谷題目剛上傳沒多久 問題一測試了兩遍 從問題三開始不再測試智譜清言&#xff08;它思考時間太長了&#xff0c;前兩個…

OCR之身份證識別

前言 OCR身份證識別是光學字符識別技術在身份證領域的應用。通過掃描或拍照獲取身份證圖像&#xff0c;利用圖像處理、深度學習等技術&#xff0c;自動提取姓名、性別、民族、出生日期、地址、身份證號等信息&#xff0c;可大幅提升信息錄入效率&#xff0c;廣泛應用于政務、金…

線性代數—向量與矩陣的范數(Norm)

參考鏈接&#xff1a; 范數&#xff08;Norm&#xff09;——定義、原理、分類、作用與應用 - 知乎 帶你秒懂向量與矩陣的范數(Norm)_矩陣norm-CSDN博客 什么是范數&#xff08;norm&#xff09;&#xff1f;以及L1,L2范數的簡單介紹_l1 norm-CSDN博客 范數&#xff08;Norm…

Java高頻面試之并發編程-08

hello啊&#xff0c;各位觀眾姥爺們&#xff01;&#xff01;&#xff01;本baby今天來報道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面試官&#xff1a;說說sleep和wait的區別&#xff1f; 1. 核心區別總結 特性sleep()wait()所屬類Thread 類的靜態方法Object 類的實例方法…

Spring-Ai-McpSever從外到內

MCP是什么 Model Context Protocol (MCP) 是一個開放協議&#xff0c;它使 LLM 應用與外部數據源和工具之間的無縫集成成為可能。無論你是構建 AI 驅動的 IDE、改善 chat 交互&#xff0c;還是構建自定義的 AI 工作流&#xff0c;MCP 提供了一種標準化的方式&#xff0c;將 LL…

ubuntu22.04 命令行修改靜態ip

傳統interfaces文件配置&#xff08;適用于舊版&#xff09;即便我們已經在桌面上配置了固定ip 這里也可以修改 ?編輯配置文件? 修改/etc/network/interfaces&#xff08;需安裝net-tools&#xff09;&#xff1a; # interfaces(5) file used by ifup(8) and ifdown(8) # In…

計算機網絡學習筆記 4-6章

第 4 章 網絡層 【考綱內容】 &#xff08;一&#xff09;網絡層的功能 異構網絡互連&#xff1b;路由與轉發&#xff1b;SDN 基本概念&#xff1b;擁塞控制 &#xff08;二&#xff09;路由算法 靜態路由與動態路由&#xff1b;距離 - 向量路由算法&#xff1…

力扣hot100_子串_python版本

一、560. 和為 K 的子數組 思路&#xff1a;這就是一道典型的前綴和的題代碼: class Solution:def subarraySum(self, nums: List[int], k: int) -> int:presum [0] * (len(nums) 1)for i, x in enumerate(nums):presum[i 1] presum[i] x # 前綴和序列需要n1個ans 0…

猿人學web端爬蟲攻防大賽賽題第15題——備周則意怠-常見則不疑

解題步驟 1、觀察抓的包 2、有個m參數&#xff0c;一看就是經過處理的&#xff0c;我們得知道m是如何組成的。看Initiator模塊。 3、還是看request函數&#xff0c;往上一看就看到了m的賦值操作。 打斷點&#xff0c;觸發。 4、看下window.m()的定義 5、比較好理解的&#x…

rag增強檢索-基于關鍵詞檢索的混合檢索模式

1. 為什么在 RAG 里要用關鍵詞檢索? 向量檢索(embedding-based retrieval)是找語義相近的內容,但有時候不夠準確。比如用戶問了具體人名、產品型號、年份,這類關鍵詞強指向性的信息,用向量檢索可能匹配不到最相關內容。**關鍵詞檢索(keyword-based retrieval)**可以直接…

純真社區IP庫離線版發布更新

純真社區IP庫離線版發布更新 發布者&#xff1a;技術分享 2005年&#xff0c;隨著中國互聯網的蓬勃發展&#xff0c;純真IP庫誕生了。作為全球網絡空間地理測繪技術的領先者&#xff0c;純真開源項目為中國互聯網行業提供了高質量的網絡空間IP庫數據。純真IP庫目前已經覆蓋超…

GitOps進化:深入探討 Argo CD 及其對持續部署的影響

什么是 GitOps&#xff1f; 雖然軟件開發生命周期的大部分已經實現自動化&#xff0c;但基礎設施仍然在很大程度上依賴于人工&#xff0c;需要專業團隊的參與。隨著當今基礎設施需求的不斷增長&#xff0c;實施基礎設施自動化變得越來越重要。現代基礎設施需要具備彈性&#x…