模式組合應用-橋接模式(一)

寫在前面

Hello,我是易元,這篇文章是我學習設計模式時的筆記和心得體會。如果其中有錯誤,歡迎大家留言指正!

文章為設計模式間的組合使用,涉及代碼較多,個人覺得熟能生巧,希望自己能從中學習到新的思維、新的靈感,希望大家也能有所收獲。


模式回顧

定義

橋接模式是一種結構型涉及模式,它旨在將抽象部分與其實現部分分離,使得它們可以獨立的變化。 橋接模式通過組合而非繼承的方式,將抽象和實現解耦,從而解決了傳統繼承在多維度變化時導致的類爆炸問題。

角色

  • 抽象化(Abstraction): 定義抽象類的接口,并維護一個指向實現化對象的引用。通常是一個抽象類,持有 實現化的引用。

  • 擴展抽象化(Refined Abstraction): 是抽象化角色的具體實現,它擴展了抽象化接口,并可以調用實現化對象的具體方法。

  • 實現化(Implementor): 定義實現類的接口,這個接口不一定要與抽象化接口完全一致,它只給出實現化角色的基本操作。通常是一個接口。

  • 具體實現化(Concrete Implementor): 是實現化角色的具體實現,實現了接口定義的操作。

思考方向

  1. 是否存在多維度變化: 如果一個類存在兩個或多個獨立變化的維度,并且這些維度都需要獨立擴展。

  2. 避免類爆炸: 當使用繼承會導致類的數量急劇增加時,橋接模式可以有效的減少類的數量,簡化系統結構。

  3. 抽象與實現是都需要獨立演化: 如果抽象和實現需要獨立的進行修改、擴展或重用。

  4. 運行時切換實現: 橋接模式允許在運行時動態的切換實現,因為抽象和實現是通過組合而不是繼承來關聯的。

橋接模式代碼練習

案例

假設需要開發一個消息通知模塊,需滿足兩個基本要求,第一個要求包含多種發送方式(如: 短信、郵件、APP內部推送),第二個要求是需要區分消息的類型(不同的類型展現形式也不同,如:緊急通知,普通通知、錯誤消息等)。

案例分析

以橋接模式為代碼開發的主要框架,以消息的類型為抽象部分,發送的方式為實現部分,使得兩個維度的變化相對獨立。

代碼

實現部分接口類
public?interface?MessageSender?{void?send(String?message);}
  • MessageSender為消息發送接口類,定義實現部分的基本功能,包含一個 send() 方法。

具體實現類
/***?短信發送*/
public?class?SmsSender?implements?MessageSender?{@Overridepublic?void?send(String?message)?{System.out.println("通過短信發送:?"?+?message);}}/***?郵件發送*/
public?class?EmailSender?implements?MessageSender?{@Overridepublic?void?send(String?message)?{System.out.println("通過郵件發送:?"?+?message);}}/***?APP推送*/
public?class?AppPushSender?implements?MessageSender?{@Overridepublic?void?send(String?message)?{System.out.println("通過APP推送:?"?+?message);}}
  • SmsSender EmailSender AppPushSender 實現部分的具體實現類,實現了 send() 接口方法,并編寫各自發送方式。

抽象部分類
public?abstract?class?AbstractMessage?{protected?MessageSender?messageSender;protected?AbstractMessage(MessageSender?messageSender)?{this.messageSender?=?messageSender;}public?abstract?void?send(String?message);
}
  • AbstractMessage 為抽象部分,抽象類中包含實現部分對象的引用 messageSender,并定義了一個 send() 方法,用于描述消息內容的類型。

抽象部分擴展類
/***?錯誤消息*/
public?class?ErrorMessage?extends?AbstractMessage?{protected?ErrorMessage(MessageSender?messageSender)?{super(messageSender);}@Overridepublic?void?send(String?message)?{messageSender.send("[錯誤]"?+?message?+?"?系統需要檢查!");}
}/***?普通消息*/
public?class?NormalMessage?extends?AbstractMessage?{protected?NormalMessage(MessageSender?messageSender)?{super(messageSender);}@Overridepublic?void?send(String?message)?{messageSender.send("[普通]"?+?message);}}/***?緊急消息*/
public?class?UrgentMessage?extends?AbstractMessage?{protected?UrgentMessage(MessageSender?messageSender)?{super(messageSender);}@Overridepublic?void?send(String?message)?{System.out.println("[緊急]"?+?message?+?"請立即處理!");}
}
  • ErrorMessage NormalMessage UrgentMessage 為抽象部分的擴展類,繼承了抽象部分類,并對抽象方法進行實現,定義各自消息類型的格式。

測試類
????@Testpublic?void?test_send()?{MessageSender?emailSend?=?new?EmailSender();MessageSender?smsSend?=?new?SmsSender();MessageSender?appPush?=?new?AppPushSender();AbstractMessage?normalEmail?=?new?NormalMessage(emailSend);AbstractMessage?urgentSms?=?new?UrgentMessage(smsSend);AbstractMessage?errorAppPush?=?new?ErrorMessage(appPush);normalEmail.send("系統升級通知");urgentSms.send("服務器負載過高");errorAppPush.send("數據庫連接失敗");AbstractMessage?normalSms?=?new?NormalMessage(smsSend);normalSms.send("每日報告已生成");}
運行結果
通過郵件發送:?[普通]系統升級通知
[緊急]服務器負載過高請立即處理!
通過APP推送:?[錯誤]數據庫連接失敗?系統需要檢查!
通過短信發送:?[普通]每日報告已生成Process?finished?with?exit?code?0

以上為橋接模式代碼應用的復習,加深印象。


橋接模式+策略模式

策略模式: 定義一系列的算法,并將每個算法封裝起來,使它們可以相互替換。策略模式讓算法獨立于使用它的客而變化。

案例

在一個電商平臺中,商品詳情頁需要支持多種展示方式(例如: 簡潔視圖、詳細視圖、畫廊視圖),同時為了應對不同的促銷活動,商品價格 的計算方式頁需要靈活切換(例如: 原價、打折價、會員價)。

模式職責

  • 橋接模式: 將商品展示方式(抽象部分)與具體的商品數據渲染(實現部分)解耦。

  • 策略模式: 封裝不同的價格計算算法,使它們可以相互替換,而不會影響客戶端。

具體設計

橋接模式
  • 抽象部分: ProductView 定義商品視圖的抽象類,持有對 ProductRenderer 的引用

  • 擴展抽象部分: SimpleProductViewDeatilProductView 等具體商品視圖

  • 實現者接口: ProductRenderer 定義商品數據渲染的接口

  • 具體實現者: HtmlProductRendererJsonProductRenderer 具體渲染器。

策略模式
  • 抽象策略: PriceCalculationStrategy 定義價格計算策略的接口

  • 具體策略: OriginalPriceStrategyDiscountPriceStrategyMemberPricesStrategy 具體價格計算策略。

  • 上下文: Product 持有對 PriceCalculationStrategy 的引用,并提供設置策略的方法。

代碼

ProductRenderer 接口
/***?產品修飾類*?<p>*?橋接模式-接口部分*/
public?interface?ProductRenderer?{String?render(String?productData);
}
  • 橋接模式中的 實現部分接口,定義了渲染商品數據的通用接口。

  • render(String productData)方法接受商品數據并返回渲染后的商品介紹。

實現部分具體實現者
/***?Html?商品渲染*?<p>*?橋接模式?-?具體實現者*/
public?class?HtmlProductRenderer?implements?ProductRenderer?{@Overridepublic?String?render(String?productData)?{return?"<html><body><h1>"?+?productData?+?"</h1></body></html>";}
}/***?Json?商品渲染*/
public?class?JsonProductRenderer?implements?ProductRenderer?{@Overridepublic?String?render(String?productData)?{return?"{\"product\":\""?+?productData?+?"\"}";}
}
  • 橋接模式中的 具體實現者,分別實現了將商品數據渲染成HTML格式和JSON格式的邏輯。

ProductView 抽象類
public?abstract?class?ProductView?{protected?ProductRenderer?productRenderer;public?ProductView(ProductRenderer?productRenderer)?{this.productRenderer?=?productRenderer;}public?void?setProductRenderer(ProductRenderer?productRenderer)?{this.productRenderer?=?productRenderer;}public?abstract?void?display(String?productData);
}
  • 橋接模式中的抽象部分,維護一個 ProductRenderer 類型的引用,作為連接抽象和實現 的橋梁。

  • setProductRenderer() 方法允許在運行時,動態改變渲染器。

  • display(String productData)抽象方法,由具體的視圖類型實現其展示邏輯。

抽象部分擴展類
/***?詳細商品視圖*?<p>*?橋接模式-擴展抽象部分*/
public?class?DetailProductView?extends?ProductView?{public?DetailProductView(ProductRenderer?productRenderer)?{super(productRenderer);}@Overridepublic?void?display(String?productData)?{System.out.println("Detail?View:?"?+?productRenderer.render("Detailed?Product?Info:?"?+?productData));}}/***?簡單視圖擴展*?<p>*?橋接模式-擴展抽象部分*/
public?class?SimpleProductView?extends?ProductView?{public?SimpleProductView(ProductRenderer?productRenderer)?{super(productRenderer);}@Overridepublic?void?display(String?productData)?{System.out.println("Simple?View:?"?+?productRenderer.render(productData));}
}
  • 橋接模式中的抽象擴展部分,代表了不同復雜度的商品視圖。

  • 通過調用 productRenderer.render()方法,將實際渲染工作委托給了具體 ProductRenderer 實現類。

PriceCalculationStrategy(策略抽象類)
/***?價格計算策略接口*?<p>*?策略模式-抽象策略*/
public?interface?PriceCalculationStrategy?{double?calculatePrice(double?originalPrice);}
  • 定義了價格計算的通用接口,calculatePrice(double originalPrice) 方法接受原始價格并返回計算后的價格。

策略實現類
/***?原始價格策略*?<p>*?策略模式-具體策略*/
public?class?OriginalPriceStrategy?implements?PriceCalculationStrategy?{@Overridepublic?double?calculatePrice(double?originalPrice)?{System.out.println("?===原始價格===?");return?originalPrice;}
}/***?會員價格策略*?<p>*?策略模式-具體策略*/
public?class?MemberPriceStrategy?implements?PriceCalculationStrategy?{/***?會員折扣價*/private?double?memberDiscount;public?MemberPriceStrategy(double?memberDiscount)?{this.memberDiscount?=?memberDiscount;}@Overridepublic?double?calculatePrice(double?originalPrice)?{System.out.println("使用會員折扣,折扣價格:?"?+?memberDiscount);return?originalPrice?-?memberDiscount;}
}/***?折扣價格策略*?<p>*?策略模式-具體策略*/
public?class?DiscountPriceStrategy?implements?PriceCalculationStrategy?{/***?折扣率*/private?double?discountRate;public?DiscountPriceStrategy(double?discountRate)?{this.discountRate?=?discountRate;}@Overridepublic?double?calculatePrice(double?originalPrice)?{System.out.println("使用折扣計算折扣價格,?折扣率:?"?+?discountRate);return?originalPrice?*?(1?-?discountRate);}
}
  • 策略模式中的具體策略類,對calculatePrice() 方法進行實現,填充了各自的計算邏輯和必須的參數。

Product(上下文)
public?class?Product?{private?String?name;private?double?originalPrice;private?PriceCalculationStrategy?priceStrategy;public?Product(String?name,?double?originalPrice,?PriceCalculationStrategy?priceStrategy)?{this.name?=?name;this.originalPrice?=?originalPrice;this.priceStrategy?=?priceStrategy;}public?void?setPriceStrategy(PriceCalculationStrategy?priceStrategy)?{this.priceStrategy?=?priceStrategy;}public?String?getName()?{return?name;}public?double?getCalculatedPrice()?{return?priceStrategy.calculatePrice(originalPrice);}
}
  • 策略模式中的上下文,持有一個 PriceCalculationStrategy 類型的引用,

  • setPriceStrategy()方法允許在運行時動態設置價格計算策略。

  • getCalculatedPrice() 方法 將價格計算的職責委托給當前設置的 PriceCalculationStrategy實現類。

測試類
????@Testpublic?void?test_bridge_strategy()?{Product?product?=?new?Product("Smart?Watch",?300.0,?new?OriginalPriceStrategy());SimpleProductView?productViewWithBridge?=?new?SimpleProductView(new?HtmlProductRenderer());productViewWithBridge.display(product.getName()?+?"?-?Original?Price:?"?+?product.getCalculatedPrice());product.setPriceStrategy(new?DiscountPriceStrategy(0.2));productViewWithBridge.setProductRenderer(new?JsonProductRenderer());productViewWithBridge.display(product.getName()?+?"?-?Discounted?Price:?"?+?product.getCalculatedPrice());System.out.println("\n?應用會員價格策略和HTML渲染器:?");product.setPriceStrategy(new?MemberPriceStrategy(25.0));productViewWithBridge.setProductRenderer(new?HtmlProductRenderer());productViewWithBridge.display(product.getName()?+?"-?Member?Price:?"?+?product.getCalculatedPrice());}
運行結果
?===原始價格===?
Simple?View:?<html><body><h1>Smart?Watch?-?Original?Price:?300.0</h1></body></html>
使用折扣計算折扣價格,?折扣率:?0.2
Simple?View:?{"product":"Smart?Watch?-?Discounted?Price:?240.0"}應用會員價格策略和HTML渲染器:?
使用會員折扣,折扣價格:?25.0
Simple?View:?<html><body><h1>Smart?Watch-?Member?Price:?275.0</h1></body></html>Process?finished?with?exit?code?0

組合優勢

  • 獨立變化: 橋接模式使得商品視圖和數據渲染可以獨立變化,策略模式使得價格計算算法可以獨立變化,兩種設計模式的結合,使得系統在多個維度上都具有高度的靈活性和可擴展性。

  • 高度復用: 渲染器和價格策略都可以被不同的商品視圖和商品對象復用。

  • 增強擴展性: 增加新的商品視圖類型、新的數據渲染方式或新的價格計算策略,都只需要添加新的類,無需修改現有代碼。

橋接模式+抽象工廠模式

提供一個接口,用于創建相關或依賴對象的家族,而無需指定它們的具體類。

案例

ERP系統報表功能需求:

  • 報表類型支持:銷售報表 庫存報表

  • 導出格式支持:PDF Excel

  • 界面主題選項:經典主題 現代主題

模式職責

  • 橋接模式: 將報表生成邏輯與導出格式實現解耦,使得二者能夠獨立變化。

  • 抽象工廠模式: 創建主題相關的報表和導出格式對象族(經典主題/現代主題)

具體設計

橋接模式
  • 抽象部分: Peport定義報告的結構,并持有一個 ExportFormat 的引用

  • 擴展抽象部分: InventoryReport SalesReport 分別生成庫存報表、銷售報表內容

  • 實現部分: ExportFormat 定義 export() 方法

  • 具體實現: PDFExport ExcelExport 分別提供基礎 PDF 、Excel 導出邏輯

抽象工廠模式
  • 抽象工廠: ThemeFactory 接口,定義了創建產品族的一系列方法

  • 具體工廠: ClassicThemeFactory ModernThemeFactory分別創建經典主題風格 和 現代主題風格的對象

  • 抽象產品: Peport

  • 具體產品: SalesReport InventoryReport PDFExport ExcelExport

代碼

ExportFormat
/***?導出格式*?<p>*?橋接模式-實現接口部分*/
public?interface?ExportFormat?{String?export(String?content);}
  • 橋接模式中的實現者接口,定義了報表導出的方法,export(String content)方法 接受原始內容,返回添加格式后的內容。

具體實現類
/***?PDF導出實現*/
public?class?PDFExport?implements?ExportFormat?{@Overridepublic?String?export(String?content)?{return?"生成PDF文檔:?"?+?content;}
}/***?Excel?導出實現*/
public?class?ExcelExport?implements?ExportFormat?{@Overridepublic?String?export(String?content)?{return?"生成Excel文件:?"?+?content;}}
  • 橋接模式中的具體實現者,分別將接受的內容導出為 PDF 和 Excel

Report
/***?報表*?<p>*?橋接模式-抽象部分*/
public?abstract?class?Report?{protected?String?title;protected?List<String>?data;protected?ExportFormat?exportFormat;public?Report(ExportFormat?exportFormat)?{this.exportFormat?=?exportFormat;}public?void?setTitle(String?title)?{this.title?=?title;}public?void?setData(List<String>?data)?{this.data?=?data;}public?abstract?String?generate();public?String?export()?{return?exportFormat.export(generate());}
}
  • 橋接模式中的抽象部分,維護一個ExportFormat 類型的引用。

  • generate() 方法用于獲取導出的數據內容

  • export() 方法委托 ExportFormat 實現類 增加導出的格式內容。

抽象部分擴展類
/***?庫存報表*/
public?class?InventoryReport?extends?Report?{public?InventoryReport(ExportFormat?exportFormat)?{super(exportFormat);this.title?=?"庫存報表";}@Overridepublic?String?generate()?{StringBuilder?content?=?new?StringBuilder(title?+?":\n");for?(String?item?:?data)?{content.append("?*?").append(item).append("\n");}return?content.toString();}
}/***?銷售報表*/
public?class?SalesReport?extends?Report?{public?SalesReport(ExportFormat?exportFormat)?{super(exportFormat);this.title?=?"銷售報表";}@Overridepublic?String?generate()?{StringBuilder?content?=?new?StringBuilder(title?+?":\n");for?(String?item?:?data)?{content.append("?-?").append(item).append("\n");}return?content.toString();}
}
  • 橋接模式中的抽象部分的擴展,分別用于獲取庫存 、銷售 報表數據。

ThemeFactory(抽象工廠類)
/***?主題對象*?<p>*?抽象工廠*/
public?interface?ThemeFactory?{Report?createSalesReport();ExportFormat?createPDFExport();Report?createInventorReport();ExportFormat?createExcelExport();
}
  • 抽象工廠模式中的抽象工廠接口,聲明創建相關產品對象的接口。

具體工廠類
/***?經典主題風格*?<p>*?具體工廠*/
public?class?ClassicThemeFactory?implements?ThemeFactory?{@Overridepublic?Report?createSalesReport()?{return?new?SalesReport(createPDFExport());}@Overridepublic?ExportFormat?createPDFExport()?{return?new?PDFExport()?{@Overridepublic?String?export(String?content)?{return?"經典主題?-?"?+?super.export(content)?+?"?(帶傳統邊框)";}};}@Overridepublic?Report?createInventorReport()?{return?new?InventoryReport(createExcelExport());}@Overridepublic?ExportFormat?createExcelExport()?{return?new?ExcelExport()?{@Overridepublic?String?export(String?content)?{return?"經典主題?-?"?+?super.export(content)?+?"?(使用傳統顏色)";}};}
}/***?現代主題風格*?<p>*?具體工廠*/
public?class?ModernThemeFactory?implements?ThemeFactory?{@Overridepublic?Report?createSalesReport()?{return?new?SalesReport(createPDFExport());}@Overridepublic?ExportFormat?createPDFExport()?{return?new?PDFExport()?{@Overridepublic?String?export(String?content)?{return?"現代主題?-?"?+?super.export(content)?+?"?(簡約設計)";}};}@Overridepublic?Report?createInventorReport()?{return?new?InventoryReport(createExcelExport());}@Overridepublic?ExportFormat?createExcelExport()?{return?new?ExcelExport()?{@Overridepublic?String?export(String?content)?{return?"現代主題?-?"?+?super.export(content)?+?"?(扁平化風格)";}};}
}
  • 抽象工廠模式中的具體工廠類,分別用于創建經典主題和現代主題風格的導出格式對象族,遵循抽象工廠模式,創建統一風格的主題產品。

測試類
????@Testpublic?void?test_report()?{List<String>?salesData?=?Arrays.asList("產品A:?100件",?"產品B:?200件",?"產品C:?150件");List<String>?inventoryData?=?Arrays.asList("倉庫1:?500件",?"倉庫2:?300件",?"倉庫3:?450件");System.out.println("?===?ERP系統報表模塊?===");System.out.println();//?使用經典主題System.out.println("【經典主題報表】");ThemeFactory?classicFactory?=?new?ClassicThemeFactory();Report?classicFactorySalesReport?=?classicFactory.createSalesReport();classicFactorySalesReport.setData(salesData);System.out.println(classicFactorySalesReport.export());System.out.println();//?使用現代主題System.out.println("【現代主題報表】");ThemeFactory?modernFactory?=?new?ModernThemeFactory();//?現代訂單報表Report?modernFactorySalesReport?=?modernFactory.createSalesReport();modernFactorySalesReport.setData(salesData);System.out.println(modernFactorySalesReport.export());//?現代庫存報表Report?modernFactoryInventorReport?=?modernFactory.createInventorReport();modernFactoryInventorReport.setData(inventoryData);System.out.println(modernFactoryInventorReport.export());}
運行結果
?===?ERP系統報表模塊?===【經典主題報表】
經典主題?-?生成PDF文檔:?銷售報表:-?產品A:?100件-?產品B:?200件-?產品C:?150件(帶傳統邊框)【現代主題報表】
現代主題?-?生成PDF文檔:?銷售報表:-?產品A:?100件-?產品B:?200件-?產品C:?150件(簡約設計)
現代主題?-?生成Excel文件:?庫存報表:*?倉庫1:?500件*?倉庫2:?300件*?倉庫3:?450件(扁平化風格)Process?finished?with?exit?code?0

組合優勢

  • 高度的靈活性: 新增報表類型或導出格式時,可以直接新增對應實現類,無需修改現有代碼。新增主圖變化擴展 ThemeFactory,新增報表邏輯擴展Report,新增導出格式則擴展ExportFormat

  • 風格的統一性: 每個工廠確保創建的對象屬于同一個主題

--

未完,下一篇接著寫,代碼量比較多。

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

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

相關文章

【clion】visual studio的sln轉cmakelist并使用clion構建32位

我想在linux上運行,所以先轉為cmake工程 例如可以把exe mfc 部分不構建,這樣ubuntu就不用移植。 先轉cmakelist,而后clion完成win32的構建,與vs構建對比,驗證腳本正確性。 Vcxproj2CMake https://github.com/gns333/Vcxproj2CMake cmakeconverter https://github.com/pave…

MySQL之分區功能

序言 隨著業務發展&#xff0c;我們維護的項目數據庫中的數據可能會越來越大&#xff0c;那么單張表的數據變多后&#xff0c;接口查詢效率可能會變慢&#xff0c;那我們就直接照抄大廠常見的分庫分表嗎&#xff1f;—— 當然不是的&#xff0c;分庫分表不是萬能的。 分庫分表…

java_spring boot 中使用 log4j2 及 自定義layout設置示例

1. log4j2對比 原始Logback 優勢 對于 Spring Boot 3.x&#xff0c;Logback 是默認日志框架&#xff0c;但在高并發、異步日志場景下&#xff0c;Log4j2 通常表現更優。當業務百萬級用戶、微服務、日志量大時&#xff1a; ? 1. Logback&#xff08;默認 Spring Boot 集成&am…

記錄Webapi Excel 導出

文章目錄1、helper2、control3、前端 axios記錄webapi excel 導出File示例.NET8.0 NPOI2.731、helper using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using System.Data; using System.IO; /// <summary> /// 導出EXCEL /// </summary> public class Exce…

VPS服務器安全審計方案:從風險評估到防護實施

隨著云計算技術的快速發展&#xff0c;VPS服務器已成為企業信息化建設的重要基礎設施。隨之而來的安全威脅也日益增多&#xff0c;如何通過專業的安全審計方案保障VPS服務器的穩定運行成為關鍵課題。本文將系統闡述從漏洞掃描到應急響應的全周期安全審計實施策略&#xff0c;幫…

libmicrohttpd 入門

libmicrohttpd 是一個小型的 C 庫&#xff0c;用于在項目中嵌入 HTTP 服務器功能。它設計簡單、輕量級&#xff0c;適合需要 HTTP 接口但不想要大型 Web 服務器開銷的應用程序。 安裝 libmicrohttpd Linux 系統 在基于 Debian/Ubuntu 的系統上&#xff1a; bash sudo apt-…

【網絡】使用 DNAT 進行負載均衡時,若未配置配套的 SNAT,回包失敗

【網絡】iptables 1 概念 【網絡】iptables 2 查看規則 【網絡】使用 DNAT 進行負載均衡時&#xff0c;若未配置配套的 SNAT&#xff0c;回包失敗 【網絡】回包路由原理 使用 DNAT 進行負載均衡時&#xff0c;若未配置配套的 SNAT&#xff0c;后端服務器將直接回包給客戶端&am…

深入解析GCC:從編譯原理到嵌入式底層實戰

繼續更新編譯器底層系列&#xff01;&#xff01;&#xff01;硬核C語言的屠龍之術&#xff1a;從GCC到匯編的底層征途&#xff08;一&#xff09;總綱&#xff1a; 恭喜你&#xff0c;決定踏上這條通往嵌入式大佬的硬核之路。這條路的起點&#xff0c;不是C語言的語法書&#…

最新MySQL面試題(2025超詳細版)

2025最新超詳細MySQL面試題 文章目錄2025最新超詳細MySQL面試題[toc]一、 SQL 和基本操作1. SQL的執行順序2. 如何優化MySQL查詢3. 常用的聚合函數4. 數據庫事務5. 事務的四大特性(ACID)6. 視圖7. MySQL中使用LIMIT子句進行分頁8. MySQL中使用變量和用戶定義的函數9. MySQL中的…

Spring Retry實戰指南_讓你的應用更具韌性

1 Spring Retry概述 1.1 什么是Spring Retry Spring Retry是Spring生態系統中的一個重要組件,專門用于處理應用程序中的重試邏輯。在分布式系統和微服務架構中,網絡通信、外部服務調用、數據庫訪問等操作都可能因為各種原因而失敗,如網絡抖動、服務暫時不可用、資源競爭等…

大數據畢業設計選題推薦-基于大數據的1688商品類目關系分析與可視化系統-Hadoop-Spark-數據可視化-BigData

?作者主頁&#xff1a;IT畢設夢工廠? 個人簡介&#xff1a;曾從事計算機專業培訓教學&#xff0c;擅長Java、Python、PHP、.NET、Node.js、GO、微信小程序、安卓Android等項目實戰。接項目定制開發、代碼講解、答辯教學、文檔編寫、降重等。 ?文末獲取源碼? 精彩專欄推薦?…

【Grafana】grafana-image-renderer配合python腳本實現儀表盤導出pdf

背景 os&#xff1a;centos7Grafana&#xff1a;v12grafana-image-renderer&#xff1a;v4.0.10插件&#xff1a;否grafana-image-renderer可以以插件形式啟動&#xff0c;也可以以單獨服務啟動&#xff0c;在centos7插件啟動時&#xff0c;報錯glibc版本太低&#xff0c;未找到…

靜/動態庫 IIC(arm) day58

十七&#xff1a;動態庫和靜態庫 庫&#xff1a;一堆可執行二進制文件的集合&#xff0c;由若干個.o文件歸并生成 一&#xff1a;靜態(鏈接)庫&#xff1a;libxxx.a 生成一個獨立的可執行程序(運行時僅需要一個文件即可) 使用方便 不需要安裝 文件比較大 多個程序使用同一個靜態…

uniapp 手寫簽名組件開發全攻略

引言在移動應用開發中&#xff0c;手寫簽名功能是一個常見的需求&#xff0c;特別是在電子合同、審批流程、金融交易等場景中。本文將詳細介紹如何基于uni-app框架開發一個高性能、功能豐富的手寫簽名組件&#xff0c;并分享開發過程中的技術要點和最佳實踐。組件概述這個簽名組…

理解JavaScript中的函數賦值和調用

&#x1f468; 作者簡介&#xff1a;大家好&#xff0c;我是Taro&#xff0c;全棧領域創作者 ?? 個人主頁&#xff1a;唐璜Taro &#x1f680; 支持我&#xff1a;點贊&#x1f44d;&#x1f4dd; 評論 ??收藏 文章目錄前言一、函數賦值二、函數調用三、 代碼示例總結前言…

交叉編譯 手動安裝 SQLite 庫 移植ARM

# 下載源碼 wget https://www.sqlite.org/2023/sqlite-autoconf-3420000.tar.gz tar -xzf sqlite-autoconf-3420000.tar.gz cd sqlite-autoconf-3420000cd /home/lxh/sqlite-autoconf-3420000 make distclean //清除下&#xff0c;因為我安裝失敗過。 ./configure --hostarm-…

翻譯記憶庫(TMX)與機器翻譯的結合應用

更多內容請見: 機器翻譯修煉-專欄介紹和目錄 文章目錄 一、核心概念解析 1.1 翻譯記憶庫 (Translation Memory, TM) 1.2 翻譯記憶交換格式 (Translation Memory eXchange, TMX) 二、為何要將兩者結合? 2.1 TM和MT的優勢是高度互補的 2.2 TMX在結合中的關鍵作用 2.3 TMX與MT的…

SpringBoot中集成eclipse.paho.client.mqttv3實現mqtt客戶端并支持斷線重連、線程池高并發改造、存儲入庫mqsql和redis示例業務流程,附資源下載

場景 SpringBoot整合MQTT服務器實現消息的發送與訂閱(推送消息與接收推送)&#xff1a; SpringBoot整合MQTT服務器實現消息的發送與訂閱(推送消息與接收推送)_服務端接收mqtt消息-CSDN博客 上面SpringBoot集成MQTT使用的是spring-integration-mqtt依賴&#xff0c;也是經常使…

【考研408數據結構-08】 圖論基礎:存儲結構與遍歷算法

&#x1f4da; 【考研408數據結構-08】 圖論基礎&#xff1a;存儲結構與遍歷算法 &#x1f3af; 考頻&#xff1a;????? | 題型&#xff1a;選擇題、綜合應用題、算法設計題 | 分值&#xff1a;約8-15分 引言 想象你正在規劃一次跨省自駕游&#xff0c;面前攤開一張復雜的…

SQL查詢語句的執行順序

好的&#xff0c;我們來詳細講解一下 SQL 查詢語句的執行順序。 很多人會誤以為 SQL 的執行順序就是我們寫的順序&#xff08;SELECT -> FROM -> WHERE -> GROUP BY -> HAVING -> ORDER BY&#xff09;&#xff0c;但實際上&#xff0c;數據庫引擎在底層處理查詢…