關于軟件設計模式的理解

系列文章
關于時間復雜度o(1), o(n), o(logn), o(nlogn)的理解

關于HashMap的哈希碰撞、拉鏈法和key的哈希函數設計

關于JVM內存模型和堆內存模型的理解

關于代理模式的理解

關于Mysql基本概念的理解

關于軟件設計模式的理解

文章目錄

  • 前言
  • 一、軟件設計模式遵循的六大原則
  • 二、學習軟件設計模式的意義
  • 三、使用率最高的設計模式有哪幾個?具體使用場景舉例
    • 1.單例模式(Singleton)
    • 2.工廠模式(Factory)
    • 3.觀察者模式(Observer)
    • 4.策略模式(Strategy)

前言

軟件設計模式(Software Design Pattern),是一套被反復使用的、關于代碼設計經驗的總結。被用來解決一些不斷重復發生的問題,是前輩們的代碼設計經驗的總結,具有一定的普遍性,可以反復使用。其目的是為了提高代碼的可重用性、代碼的可讀性和代碼的可靠性

一、軟件設計模式遵循的六大原則

設計模式通常遵循的六大原則是:

開放封閉原則(Open/Closed Principle,OCP): 軟件實體(類、模塊、函數等)應該對擴展開放,對修改關閉。這意味著在不修改現有代碼邏輯的情況下,能夠通過擴展來增加新的功能。

單一職責原則(Single Responsibility Principle,SRP): 一個類應該只負責一種類型的任務或職責。

里氏替換原則(Liskov Substitution Principle,LSP): 子類型必須能夠替換掉它們的父類型,而不影響程序的正確性。

依賴倒置原則(Dependency Inversion Principle,DIP): 應該依賴于接口或抽象類,而不是具體的實現。

接口隔離原則(Interface Segregation Principle,ISP): 一個類不應該依賴它不需要的接口。

合成/聚合復用原則(Composition/Aggregation Reuse Principle,CARP): 應該優先使用對象組合或聚合,而不是繼承來實現代碼復用。

這些原則提供了指導,幫助開發人員設計出靈活、可維護、可擴展和易于理解的軟件系統。雖然并不是每種設計模式都嚴格遵循這些原則,但設計模式通常是以這些原則為基礎來提供解決特定問題的通用方案

二、學習軟件設計模式的意義

設計模式的本質是面向對象設計原則的實際運用,是對類的封裝性、繼承性和多態性以及類的關聯關系和組合關系的充分理解。正確使用設計模式具有以下優勢。:

  1. 可以提高程序員的思維能力、編程能力和設計能力。
  2. 可以使程序設計更加標準化、代碼編制更加工程化,使軟件開發效率大大提高,從而縮短軟件的開發周期。
  3. 可以使設計的代碼可復用性高、可讀性強、可靠性高、靈活性好、可維護性強。

三、使用率最高的設計模式有哪幾個?具體使用場景舉例

1.單例模式(Singleton)

場景舉例: 當系統中需要確保一個類只有一個實例,并提供全局訪問點時,通常使用單例模式。如數據庫連接池、日志管理器等

代碼案例:

步驟 1: 創建單例類

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class DatabaseConnection {// 數據庫連接相關配置private static final String URL = "jdbc:mysql://localhost:3306/mydatabase";private static final String USERNAME = "username";private static final String PASSWORD = "password";// 私有靜態變量,保存類的唯一實例private static DatabaseConnection instance;// 數據庫連接對象private Connection connection;// 私有構造函數,防止外部直接創建對象private DatabaseConnection() {try {// 創建數據庫連接connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);} catch (SQLException e) {e.printStackTrace();}}// 公有靜態方法,返回唯一實例public static DatabaseConnection getInstance() {if (instance == null) {// 確保線程安全synchronized (DatabaseConnection.class) {if (instance == null) {instance = new DatabaseConnection();}}}return instance;}// 獲取數據庫連接對象public Connection getConnection() {return connection;}
}

步驟 2: 使用單例類

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class Main {public static void main(String[] args) {// 獲取數據庫連接Connection connection = DatabaseConnection.getInstance().getConnection();// 執行數據庫操作try {PreparedStatement statement = connection.prepareStatement("SELECT * FROM users");ResultSet resultSet = statement.executeQuery();while (resultSet.next()) {System.out.println("User ID: " + resultSet.getInt("id") + ", Name: " + resultSet.getString("name"));}resultSet.close();statement.close();} catch (SQLException e) {e.printStackTrace();}}
}

解釋
單例模式的核心: 私有構造函數和一個返回實例的公有靜態方法。
線程安全: 使用雙重檢查鎖定確保在多線程環境下安全創建實例。
延遲初始化: 實例在類被加載時不會創建,在首次需要時才創建,節省資源。
數據庫連接池: 這種方式也可以用于實現簡單的數據庫連接池,通過控制并發訪問來管理連接數,提高數據庫連接的效率和資源利用率。
這種實現方式在實際應用中非常有用,特別是在需要頻繁訪問數據庫的情況下,可以減少連接的開銷和管理成本。

2.工廠模式(Factory)

場景舉例: 當需要創建多個具有相似功能的對象時,使用工廠模式可以將對象的創建邏輯封裝在一個工廠類中,提高代碼的靈活性和可維護性。如數據庫驅動管理等

代碼案例:

步驟 1: 創建接口

import java.sql.Connection;public interface DatabaseConnection {Connection getConnection();
}

步驟 2: 創建具體實現類

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class MySQLConnection implements DatabaseConnection {// MySQL數據庫連接相關配置private static final String URL = "jdbc:mysql://localhost:3306/mydatabase";private static final String USERNAME = "username";private static final String PASSWORD = "password";@Overridepublic Connection getConnection() {Connection connection = null;try {// 創建MySQL數據庫連接connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);} catch (SQLException e) {e.printStackTrace();}return connection;}
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class PostgreSQLConnection implements DatabaseConnection {// PostgreSQL數據庫連接相關配置private static final String URL = "jdbc:postgresql://localhost:5432/mydatabase";private static final String USERNAME = "username";private static final String PASSWORD = "password";@Overridepublic Connection getConnection() {Connection connection = null;try {// 創建PostgreSQL數據庫連接connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);} catch (SQLException e) {e.printStackTrace();}return connection;}
}

步驟 3: 創建工廠類

public class ConnectionFactory {public static DatabaseConnection getDatabaseConnection(String dbType) {if (dbType.equalsIgnoreCase("MySQL")) {return new MySQLConnection();} else if (dbType.equalsIgnoreCase("PostgreSQL")) {return new PostgreSQLConnection();}return null;}
}

步驟 4: 使用工廠模式獲取數據庫連接

import java.sql.Connection;public class Main {public static void main(String[] args) {// 獲取MySQL數據庫連接DatabaseConnection mysqlConnection = ConnectionFactory.getDatabaseConnection("MySQL");Connection mysqlConn = mysqlConnection.getConnection();// 獲取PostgreSQL數據庫連接DatabaseConnection postgresConnection = ConnectionFactory.getDatabaseConnection("PostgreSQL");Connection postgresConn = postgresConnection.getConnection();// 使用數據庫連接執行操作...}
}

解釋
工廠模式的核心: 根據條件動態創建對象,將創建邏輯封裝在工廠類中,客戶端無需關心具體的創建細節。
可擴展性: 當需要新增其他類型的數據庫連接時,只需在工廠類中添加相應的創建邏輯即可,不需要修改客戶端代碼。
解耦: 客戶端與具體數據庫連接類之間解耦,通過工廠類進行統一管理,降低了代碼的耦合度。
工廠模式能夠很好地應對數據庫驅動管理場景中的需求變化,使得代碼更加靈活和可維護。

3.觀察者模式(Observer)

場景舉例: 當一個對象的狀態發生改變時,需要通知其他相關對象,并自動更新它們的狀態時,通常使用觀察者模式。如消息訂閱與發布系統等

代碼案例:
步驟 1: 創建主題接口
首先,定義一個主題接口,用于注冊、刪除和通知觀察者。

public interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}

步驟 2: 創建觀察者接口
然后,定義一個觀察者接口,用于接收主題的通知。

public interface Observer {void update(String message);
}

步驟 3: 創建具體主題類
接下來,創建具體的主題類,實現主題接口,并維護觀察者列表,以及在狀態變化時通知觀察者。

import java.util.ArrayList;
import java.util.List;public class MessageTopic implements Subject {private List<Observer> observers;private String message;public MessageTopic() {this.observers = new ArrayList<>();}@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(message);}}public void setMessage(String message) {this.message = message;notifyObservers();}
}

步驟 4: 創建具體觀察者類
然后,創建具體的觀察者類,實現觀察者接口,并在接收到通知時執行相應的操作。

public class MessageSubscriber implements Observer {private String name;public MessageSubscriber(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " received message: " + message);}
}

步驟 5: 使用觀察者模式
最后,在應用程序中使用觀察者模式。

public class Main {public static void main(String[] args) {// 創建主題MessageTopic topic = new MessageTopic();// 創建觀察者Observer subscriber1 = new MessageSubscriber("Subscriber 1");Observer subscriber2 = new MessageSubscriber("Subscriber 2");// 注冊觀察者topic.registerObserver(subscriber1);topic.registerObserver(subscriber2);// 發布消息topic.setMessage("Hello, world!");}
}

解釋
主題接口: 定義了注冊、刪除和通知觀察者的方法。
觀察者接口: 定義了觀察者需要實現的更新方法。
具體主題類: 實現了主題接口,維護了觀察者列表,并在狀態變化時通知所有觀察者。
具體觀察者類: 實現了觀察者接口,定義了接收通知時的具體行為。
使用觀察者模式: 創建主題對象,創建觀察者對象并注冊到主題中,然后發布消息。所有注冊的觀察者都會接收到消息通知并執行相應的操作。
觀察者模式非常適用于消息訂閱與發布場景,可以實現松耦合的通信機制,讓發布者和訂閱者之間的關系更加靈活。

4.策略模式(Strategy)

場景舉例: 當需要在運行時根據不同的情況選擇算法或行為時,使用策略模式可以將不同的算法封裝成不同的策略類,使得算法的變化獨立于使用算法的客戶。如支付系統中的支付策略等

代碼案例:

步驟 1: 創建支付策略接口
首先,定義一個支付策略接口,用于定義支付的方法。

public interface PaymentStrategy {void pay(double amount);
}

步驟 2: 創建具體的支付策略類
然后,創建具體的支付策略類,實現支付策略接口,每個具體的支付策略類代表一種支付方式,例如信用卡支付、支付寶支付、微信支付等

public class CreditCardPayment implements PaymentStrategy {private String cardNumber;private String expiryDate;private String cvv;public CreditCardPayment(String cardNumber, String expiryDate, String cvv) {this.cardNumber = cardNumber;this.expiryDate = expiryDate;this.cvv = cvv;}@Overridepublic void pay(double amount) {System.out.println("Paid " + amount + " via credit card.");}
}public class AlipayPayment implements PaymentStrategy {private String account;public AlipayPayment(String account) {this.account = account;}@Overridepublic void pay(double amount) {System.out.println("Paid " + amount + " via Alipay.");}
}public class WechatPayment implements PaymentStrategy {private String account;public WechatPayment(String account) {this.account = account;}@Overridepublic void pay(double amount) {System.out.println("Paid " + amount + " via WeChat.");}
}

步驟 3: 創建上下文類
接下來,創建上下文類,用于持有具體的支付策略對象,并提供支付方法。

public class PaymentContext {private PaymentStrategy paymentStrategy;public PaymentContext(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void pay(double amount) {paymentStrategy.pay(amount);}
}

步驟 4: 使用策略模式
最后,在應用程序中使用策略模式進行支付。

public class Main {public static void main(String[] args) {// 創建支付上下文PaymentContext paymentContext = new PaymentContext(new CreditCardPayment("1234 5678 9012 3456", "12/24", "123"));// 進行支付paymentContext.pay(100.0);// 切換支付方式paymentContext.setPaymentStrategy(new AlipayPayment("example@example.com"));// 進行支付paymentContext.pay(200.0);}
}

解釋
支付策略接口: 定義了支付的方法。
具體的支付策略類: 實現了支付策略接口,每個類代表一種支付方式,實現了具體的支付邏輯。
支付上下文類: 持有具體的支付策略對象,并提供支付方法,客戶端通過上下文類進行支付。
使用策略模式: 創建支付上下文對象,根據需要設置不同的支付策略,然后進行支付操作。
策略模式能夠有效地解耦客戶端和具體的支付策略,使得支付系統更加靈活,易于擴展和維護。

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

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

相關文章

前端面試題日常練-day35 【面試題】

題目 希望這些選擇題能夠幫助您進行前端面試的準備&#xff0c;答案在文末。 1. 以下哪個是使用jQuery選擇所有具有CSS類名"myClass"的元素的正確語法&#xff1f; a) $(".myClass") b) $("myClass") c) $("#myClass") d) $("…

FURNet問題

1. 為什么選擇使用弱監督學習&#xff1f; 弱監督學習減少了對精確標注數據的依賴&#xff0c;這在醫學圖像處理中尤為重要&#xff0c;因為高質量標注數據通常需要大量專業知識和時間。弱監督學習通過利用少量標注數據或粗略標注數據來訓練模型&#xff0c;降低了數據準備的成…

元組推導式

自學python如何成為大佬(目錄):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 使用元組推導式可以快速生成一個元組&#xff0c;它的表現形式和列表推導式類似&#xff0c;只是將列表推導式中的“[]”修改為“()”。例如&#xf…

python深入解析字符串操作的八大神技

新書上架~&#x1f447;全國包郵奧~ python實用小工具開發教程http://pythontoolsteach.com/3 歡迎關注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目錄 一、字符串的長度與切片 示例代碼 二、去除多余的空格 示例代碼 三、字符串的開頭與包含…

元組的創建和刪除

目錄 使用賦值運算符直接創建元組 創建空元組 創建數值元組 刪除元組 自學python如何成為大佬(目錄):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 元組&#xff08;tuple&#xff09;是Python中另一個重要的序列結構&#…

JavaScript 獲取 HTML 中特定父元素下的子元素

JavaScript 獲取 HTML 中特定父元素下的子元素 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>查找子元素示例</title> </head> <body><div id"parent"><p&…

CTF-web-攻防世界-2

1、newscenter (1)、訪問網站&#xff0c;一個搜索欄&#xff0c;像是SQL注入漏洞&#xff0c;brup抓包嘗試一下。 輸入2/0、一個單引號、兩個單引號、一個雙引號、兩個雙引號等。發現只有一個單引號時&#xff0c;響應包content-length字段有非常明顯的變化為0。說明有可能是…

關于堆排序

今天我們不刷力扣了&#xff0c;我們來復習&#xff08;手撕&#xff09;一下數據結構中的八大排序算法之一&#xff0c;堆排序 基本概念&#xff1a; 堆是一種特殊的樹形數據結構&#xff0c;即完全二叉樹。 堆分為大頂堆和小頂堆&#xff1a; 大頂堆&#xff1a;每個節點的值…

OrangePi KunPengPro | 開發板開箱測評之學習與使用

OrangePi KunPengPro | 開發板開箱測評之學習與使用 時間&#xff1a;2024年5月23日20:51:12 文章目錄 OrangePi KunPengPro | 開發板開箱測評之學習與使用概述1.參考2.資料、工具3.使用3-1.通過串口登錄系統3-2.通過SSH登錄系統3-3.安裝交叉編譯工具鏈3-4.復制文件到設備3-5.第…

【組合數學】常考試題答案

一、單項選擇題&#xff08;每小題3分&#xff0c;共15分&#xff09; 1. 用3個“1”和4個“0”能組成&#xff08; &#xff09;個不同的二進制數字。 A. 35 B. 36, C. 37, D. 38 2. 整除300的正整數的個數為&#xff08;  &#xff09;。 A. 14…

Anaconda+CUDA+CUDNN+Pycharm+Pytorch安裝教程(第一節 Anconda安裝)

1.選擇和對應的anconda版本 官網地址&#xff1a;Index of / (anaconda.com) 下載地址&#xff1a;Index of /anaconda/archive/ | 清華大學開源軟件鏡像站 | Tsinghua Open Source Mirror 2.安裝流程 (1)下載安裝包 (2)點擊next &#xff08;3&#xff09;點擊I agree &a…

解決Flutter位于懸浮窗口時,應用Logo不更新問題

問題描述 我已經更換了應用Logo&#xff0c;但是發現應用處于懸浮窗口時&#xff0c;logo還是更改之前的&#xff1f;下面的圖片只是示意。 解決方案 終端命令 rm -rf ~/Library/Developer/Xcode/DerivedData2.xcode視圖內解決 先在頂部找到 Xcode --> Setting --> Lo…

操作系統入門系列-MIT6.828(操作系統工程)學習筆記(二)----課程實驗環境搭建(wsl2+ubuntu+quem+xv6)

MIT6.S081&#xff08;操作系統&#xff09;學習筆記 操作系統入門系列-MIT6.828&#xff08;操作系統&#xff09;學習筆記&#xff08;一&#xff09;---- 操作系統介紹與接口示例 操作系統入門系列-MIT6.828&#xff08;操作系統工程&#xff09;學習筆記&#xff08;二&am…

Java面向對象-常用類(日期時間類)

常用類-日期時間類 Date&#xff08;java.util.Date&#xff09; – 日期類 SimpleDateFormat – 格式化日期類 Calendar – 日歷類 1 Date類 java.util.Date類表示特定的瞬間&#xff0c;精確到毫秒。 package com.qf.datetime;import java.util.Date;public class Test01 {…

ubantu20.04 跑通ros2版的orbslam2

我的歷程 先編譯的非ros版的robslam2&#xff08;非常詳細&#xff09; ubuntu20.04配置并編譯ORB-SLAM2_ubuntu20.04安裝orb-lslam2-CSDN博客 然后裝ros2&#xff08;非常詳細&#xff09; 詳細介紹如何在ubuntu20.04中安裝ROS系統&#xff0c;超快完成安裝&#xff08;最…

C#解析xml文件

1、示例 <?xml version"1.0" encoding"utf-8" standalone"no"?><DATA><ITEMS><ITEM><ID>01<ID/><CODE>0001<CODE><NAME>測試1<NAME/></ITEM><ITEM><ID>02<…

福昕PDF編輯器自定義快捷方式

你是否為用不慣福昕PDF編輯器自帶的快捷鍵而發愁&#xff1f;今天&#xff0c;我和大家分享一下如何設置自己想要的快捷鍵方式&#xff0c;希望能對大家有幫助。 步驟一&#xff1a;打開福昕PDF編輯&#xff0c;并找到更多命令 步驟二&#xff1a;切換到鍵盤一欄&#xff0c;并…

分布式專題

一&#xff1a;分布式事務 1、理論基礎 分布式事務主要區分本地事務 什么是本地事務&#xff08;Local Transaction&#xff09;&#xff1f;本地事務也稱為數據庫事務或傳統事務&#xff08;相對于分布式事務而言&#xff09;。尤其對于數據庫而言&#xff0c;為了數據安全…

Android 多張圖片合成GIF

直接用嗶哩嗶哩弄的一個庫&#xff0c;傳送門&#xff1a;https://github.com/bilibili/BurstLinker 他那個庫的文檔寫的比較簡陋&#xff0c;所以我決定&#xff0c;我也寫得十分簡陋 引用&#xff1a; api com.bilibili:burst-linker:0.0.13 使用&#xff1a; /*** param i…

Docker快速搭建Oracle服務

服務器&#xff1a;CentOS7.9 1.安裝docker yum install -y docker 2. 設置鏡像加速 修改 /etc/docker/daemon.json 文件并添加上 registry-mirrors 鍵值 阿里云的docker鏡像需要自己注冊賬號&#xff0c;也可以不注冊賬號&#xff0c;直接使用下面的連接。 也可以寫入多…