適配器模式:如何讓不相容的介面變得相容

来源:https://www.cnblogs.com/waynaqua/archive/2023/09/08/17688134.html
-Advertisement-
Play Games

在軟體開發中,我們經常會遇到這樣的情況:我們需要使用一個現有的類或者介面,但它與我們系統的目標介面不相容,而我們又不能修改它。這時候,我們該怎麼辦呢?大多數情況下我們都可以使用適配器模式來解決這個問題,**本文將從以下四個方面講解適配器模式**。 - 簡介 - 優缺點 - 應用場景 - Java 代 ...


在軟體開發中,我們經常會遇到這樣的情況:我們需要使用一個現有的類或者介面,但它與我們系統的目標介面不相容,而我們又不能修改它。這時候,我們該怎麼辦呢?大多數情況下我們都可以使用適配器模式來解決這個問題,本文將從以下四個方面講解適配器模式

  • 簡介
  • 優缺點
  • 應用場景
  • Java 代碼示例

簡介

適配器模式(Adapter Pattern)是一種結構型設計模式,它可以將一個介面轉換成客戶端所期待的另一個介面,從而使原本由於介面不相容而不能一起工作的類可以一起工作。適配器模式也稱為包裝器模式(Wrapper Pattern),因為它通過一個包裝類(即適配器)來包裝不相容的介面,並提供統一的目標介面。適配器模式可以在運行時根據需要選擇不同的適配器來適配不同的被適配者。

對象適配器模式的各角色定義如下。

  • Target(目標介面):客戶端要使用的目標介面標準,對應下文中的三相插孔介面 TriplePin。
  • Adapter(適配器):實現了目標介面,負責適配(轉換)被適配者的介面 specificRequest()為目標介面 request(),對應本章下文中的電視機專屬適配器類 TriplePinAdapter。
  • Adaptee(被適配者):被適配者的介面標準,目前不能相容目標介面的問題介面,可以有多種實現類,對應下文中的兩相插孔介面 DualPin。
  • Client(客戶端):目標介面的使用者。

推薦博主開源的 H5 商城項目waynboot-mall,這是一套全部開源的微商城項目,包含三個項目:運營後臺、H5 商城前臺和服務端介面。實現了商城所需的首頁展示、商品分類、商品詳情、商品 sku、分詞搜索、購物車、結算下單、支付寶/微信支付、收單評論以及完善的後臺管理等一系列功能。 技術上基於最新得 Springboot3.0、jdk17,整合了 MySql、Redis、RabbitMQ、ElasticSearch 等常用中間件。分模塊設計、簡潔易維護,歡迎大家點個 star、關註博主。

github 地址:https://github.com/wayn111/waynboot-mall

優缺點

適配器模式的優點有:

  • 適配器模式可以增強程式的可擴展性,通過使用適配器,可以在不修改原有代碼的基礎上引入新的功能或者介面。
  • 適配器模式可以提高類的復用性,通過使用適配器,可以將已有的類或者介面重新組合和封裝,使其符合新的需求。
  • 適配器模式可以增加類的透明度,通過使用適配器,客戶端只需要關註目標介面,而無需瞭解被適配者的具體實現。
  • 適配器模式可以靈活地切換不同的被適配者,通過使用不同的適配器,可以動態地選擇不同的被適配者來滿足不同的場景。

適配器模式的缺點有:

  • 適配器模式會增加系統的複雜性,過多地使用適配器會使系統變得零亂和難以理解。
  • 適配器模式可能會降低系統的性能,因為每次調用目標介面時都需要經過適配器的轉換。
  • 適配器模式可能會違反開閉原則,如果目標介面發生變化,則需要修改所有的適配器類。

應用場景

適配器模式適用於以下場景:

  • 當需要在一個已有系統中引入新的功能或者介面時,它與系統的目標介面不相容,但又不能修改原有代碼時,可以使用適配器模式。例如在一個資料庫操作系統中,如果想要支持多種類型的資料庫源,但系統只提供了一個固定類型資料庫源的操作介面時,可以使用一個資料庫源操作適配器來將不同類型資料庫源轉換成統一類型資料庫源。
  • 當需要在多個獨立開發的系統或者組件之間進行協作時,但由於各自採用了不同的介面或者協議時,可以使用適配器模式。例如在一個分散式服務系統中,如果想要讓不同語言編寫的服務之間進行通信和調用,但各自採用了不同的通信協議和數據格式時,可以使用一個服務通信適配器來將不同協議和數據格式轉換成統一協議和數據格式。

Java 代碼示例

舉一個生活中常見的實例,我們新買了一臺電視機,其電源插頭是兩相的,不巧的是牆上的插孔卻是三相的,這時電視機便無法通電使用,我們以代碼來重現這個場景。

  1. 定義目標介面:三相插口 TriplePin,其中 3 個參數 l、n、e 分別對應火線(live)、零線(null)和地線(earth)。
public interface TriplePin {

    public void electrify(int l, int n, int e);
}
  1. 定義被適配者介面:兩項插口 DualPin,可以看到參數中缺少了地線 e 參數。
public interface DualPin {

    public void electrify(int l, int n);
}

  1. 添加被適配者介面具體實現類:TV,可以看到 TV 實現的是兩相介面,所在無法直接在三項介面中使用。
public class TV implements DualPin {
    @Override
    public void electrify(int l, int n) {
        System.out.println("火線通電:" + l + ",零線通電:" + n);
        System.out.println("電視開機");
    }
}

  1. 定義適配器類:三項介面適配器 TriplePinAdapter,實現了三項介面並且包含兩項介面屬性,在 electrify 方法中調用被適配設備的兩插通電方法,忽略地線參數 e,以此來完成三項介面對兩項介面的相容。

這也就意味著 TriplePinAdapter 類能幫助我們將 TV 類與三項介面相容。

public class TriplePinAdapter implements TriplePin {

    private DualPin dualPin;

    public TriplePinAdapter(DualPin dualPin) {
        this.dualPin = dualPin;
    }

    @Override
    public void electrify(int l, int n, int e) {
        // 調用被適配設備的兩插通電方法,忽略地線參數e
        dualPin.electrify(l, n);
    }
}
  1. 定義客戶端類
public class Client {

    public static void main(String[] args) {
        DualPin dualPinDevice = new TV();
        TriplePin triplePinDevice = new TriplePinAdapter(dualPinDevice);
        triplePinDevice.electrify(1, 0, -1);
    }
}

輸出結果如下:

火線通電:1,零線通電:0
電視開機

總結

通過利用適配器模式對系統進行擴展後,我們就不必再為解決相容性問題去暴力修改類介面了,轉而通過適配器,以更為優雅、巧妙的方式將兩側“對立”的介面“整合”在一起,順利化解雙方難以調和的矛盾,最終使它們順利接通。

關註公眾號【waynblog】每周分享技術乾貨、開源項目、實戰經驗、國外優質文章翻譯等,您的關註將是我的更新動力!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 此篇文章用於記錄柏成從零開發一個canvas九宮格手勢解鎖器的歷程。我們基於 canvas 實現了一款簡單的九宮格手勢解鎖器,用戶可以通過在九宮格中繪製特定的手勢來解鎖。 ...
  • ##一、定義 **使用原型實例指定待創建對象的類型,並且通過複製這個原型來創建新的對象。原型模式是一種創建型模式。** ##二、描述 **包含以下三個角色:** ![](https://img2023.cnblogs.com/blog/1780813/202305/1780813-202305271 ...
  • 本文給大家介紹了什麼是"編程範式",選擇合適的編程範式可以提高代碼的可讀性、可維護性和可擴展性。 一、 什麼是編程範式? "編程範式"是一種編程思想的總稱,它是指在編寫程式時所採用的基本方法和規範。常見的編程範式有面向對象、函數式、邏輯式等。 選擇合適的編程範式可以提高代碼的可讀性、可維護性和可擴展 ...
  • 淺聊一下SpringMVC的核心組件以及通過源碼瞭解其執行流程 MVC作為WEB項目開發的核心環節,正如三個單詞的分解那樣,Controller(控制器)將View(視圖、用戶客戶端)與Model(javaBean:封裝數據)分開構成了MVC,今天我們淺聊一下SpringMVC的相關組件以及通過源碼... ...
  • ### 原型模式 #### 案例引入 ##### 克隆羊問題 有一隻羊,姓名為tom,年齡為1,顏色為白色,編寫程式創建和tom羊屬性完全相同的羊。 ##### 傳統方式解決 代碼實現 ```java public class Sheep { private String name; private ...
  • 結構體(簡稱struct)用於創建不同數據類型的成員集合,放入一個單一的變數中。雖然數組用於將相同數據類型的多個值存儲在單一變數中,但結構體用於將不同數據類型的多個值存儲在單一變數中。結構體對於將數據組合在一起以創建記錄非常有用。 聲明結構體 要在Go中聲明一個結構體,請使用type和struct關 ...
  • ### 前言 上篇文章 [13分鐘聊聊併發包中常用同步組件並手寫一個自定義同步組件](https://juejin.cn/post/7274475842998042665) 聊到併發包中常用的同步組件,並且還手把手實現了自定義的同步組件 本篇文章來聊聊併發包下的另一個核心-線程池 閱讀本文大概12分 ...
  • # Python初步瞭解裝飾器 - 裝飾器的概念 - 裝飾器的簡單使用 - 裝飾器的進階 - 裝飾器的練習 - 裝飾器的固定模塊 - 裝飾器的語法糖 ## 裝飾器的概念 ```python 裝飾器它不是一個新的知識點,它是有之前我們學習的名稱空間、函數嵌套、閉包函數等知識點彙總而來 器:工具 裝飾: ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...