適配器模式在 MyBatis 中的妙用,面試可以拿來吹了!

来源:https://www.cnblogs.com/javastack/archive/2022/07/06/16450749.html
-Advertisement-
Play Games

作者:須臾之餘 地址:https://my.oschina.net/u/3995125 寫在前面:設計模式源於生活,而又高於生活! 什麼是適配器模式 定義:將一個系統的介面轉換成另外一種形式,從而使原來不能直接調用的介面變得可以調用。 適配器模式角色劃分 適配器模式涉及3個角色: 1.源(Adapt ...


作者:須臾之餘
地址:https://my.oschina.net/u/3995125

寫在前面:設計模式源於生活,而又高於生活!

什麼是適配器模式

定義:將一個系統的介面轉換成另外一種形式,從而使原來不能直接調用的介面變得可以調用。

適配器模式角色劃分

適配器模式涉及3個角色:
1.源(Adaptee):需要被適配的對象或類型,相當於插頭。
2.適配器(Adapter):連接目標和源的中間對象,相當於插頭轉換器。
3.目標(Target):期待得到的目標,相當於插座。
適配器模式包括3種形式:類適配器模式、對象適配器模式、介面適配器模式(或又稱作預設適配器模式)。

適配器模式應用場景

1、新老版本介面的相容
2、Mybatis多種日誌框架的整合

適配器創建的方式

1.對象適配器(組合模式)
2.類適配器(繼承模式)

適配器快速入門例子

比如早期的時候 V1 版本訂單介面的入參為 Map 類型,隨著業務的更新和迭代在 V2 版本的時候該訂單介面的入參需要支持 List 的類型? 請問不改變的該介面代碼的情況下,如何支持 List 類型。

1. 源(Adaptee):需要被適配的對象或類型,相當於插頭。

public void froOrderMap(Map map) {
    for (int i = 0; i < map.size(); i++) {
        // 使用I作為MapKey獲取數據
        String value = (String) map.get(i);
        System.out.println("value:" + value);
    }
}

2. 目標(Target):期待得到的目標,相當於插座。

public interface List<E> extends Collection<E> {
    ......
    int size();
    E get(int index);
    E set(int index, E element);
}

3. 適配器(Adapter):連接目標和源的中間對象,相當於插頭轉換器

public class ListAdapter extends HashMap {

    private List list;
    public ListAdapter(List list) {
        this.list = list;
    }
    @Override
    public int size() {
        return list.size();
    }
    @Override
    public Object get(Object key) {
        return list.get(Integer.valueOf(key.toString()).intValue());
    }
}

測試運行效果

public class Test {
    public static void main(String[] args) {
        // 1.獲取集合類型用戶
        List member = new MemberService().getMember();
        //new OrderService().froOrderMap(member);
        ListAdapter listAdapter = new ListAdapter(member);
        new OrderService().froOrderMap(listAdapter);
    }
}

使用適配器模式實現日誌收集

比如設計一個日誌收集系統,可能會考慮文件寫入、也可能考慮寫入 MQ、也可能考慮寫入資料庫等。

對象適配器方式實現

定義基本實體類

@Data
public class LogBean {
    /**
     * 日誌ID
     */
    private String logId;
    /**
     * 日誌內容
     */
    private String logText;
}

1. 源目標介面

public interface LogWriteFileService {

    /**
     * 將日誌寫入到文件中
     */
    void logWriteFile();
    /**
     * 從本地文件中讀取日誌
     *
     * @return
     */
    List<LogBean> readLogFile();
}

1. 源目標介面實現類

public class LogWriteFileServiceImpl implements LogWriteFileService {
    @Override
    public void logWriteFile() {
        System.out.println(">>>將日誌寫入文件中...");
    }
  @Override
    public List<LogBean> readLogFile() {
        LogBean log1 = new LogBean();
        log1.setLogId("0001");
        log1.setLogText("Tomcat啟動成功..");

        LogBean log2 = new LogBean();
        log2.setLogId("0002");
        log2.setLogText("Jetty啟動成功..");
        List<LogBean> listArrayList = new ArrayList<LogBean>();
        listArrayList.add(log1);
        listArrayList.add(log2);
        return listArrayList;
    }
}

2. 目標介面

public interface LogWriteDbService {

    /**
     * 將日誌寫入到資料庫中
     */
   public void writeDbFile(LogBean logBean);
}

2. 適配器

//LogAdapter :適配器
//LogWriteDbService:目標
public class LogAdapter implements LogWriteDbService {
    //源介面
    private LogWriteFileService logWriteFileService;

    public LogAdapter(LogWriteFileService logWriteFileService) {
        this.logWriteFileService = logWriteFileService;
    }

    @Override
    public void writeDbFile(LogBean logBean) {
        // 1.從文件中讀取日誌文件
        List<LogBean> logBeans = logWriteFileService.readLogFile();
        //目標
        // 2.寫入到資料庫中
        logBeans.add(logBean);
        System.out.println(">>>將數據寫入到資料庫中..");
        // 3.寫入到本地文件中
        logWriteFileService.logWriteFile();
    }
}

適配器模式優缺點

適配器模式的優點
  更好的復用性
系統需要使用現有的類,而此類的介面不符合系統的需要。那麼通過適配器模式就可以讓這些功能得到更好的復用。
更好的擴展性
在實現適配器功能的時候,可以調用自己開發的功能,從而自然地擴展系統的功能。

適配器模式的缺點
  過多的使用適配器,會讓系統非常零亂,不易整體進行把握。比如,明明看到調用的是A介面,其實內部被適配成了B介面的實現,一個系統如果太多出現這種情況,無異於一場災難。因此如果不是很有必要,可以不使用適配器,而是直接對系統進行重構。

Mbatis 日誌收集分析

Java開發中經常用到的日誌框架有很多,Log4j、Log4j2、slf4j等等,Mybatis定義了一套統一的日誌介面供上層使用,併為上述常用的日誌框架提供了相應的適配器

在Mybatis的日誌模塊中就是使用了適配器模式。Mybatis內部在使用日誌模塊時,使用了其內部介面 org.apache.ibatis.logging.Log,但是常用的日誌框架的對外介面各不相同,Mybatis為了復用和集成這些第三方日誌組件,在其日誌模塊中,提供了多種Adapter,將這些第三方日誌組件對外介面適配成org.apache.ibatis.logging.Log,這樣Myabtis 就可以通過Log介面調用第三方日誌了

源碼分析圖

源碼剖析

Mybatis Log 介面:相當於源介面

package org.apache.ibatis.logging;

public interface Log {
  boolean isDebugEnabled();
  boolean isTraceEnabled();
  void error(String s, Throwable e);
  void error(String s);
  void debug(String s);
  void trace(String s);
  void warn(String s);
}

Mybatis 源介面實現類

適配器第一種

package org.apache.ibatis.logging.slf4j;

import org.apache.ibatis.logging.Log;
import org.slf4j.Logger;

//Slf4jLoggerImpl :相當於適配器
//Log :相當於源介面
class Slf4jLoggerImpl implements Log {

  //Logger:相當於目標介面
  private Logger log;

  public Slf4jLoggerImpl(Logger logger) {
    //源=目標
    log = logger;
  }

適配器第二種

package org.apache.ibatis.logging.log4j2;

import org.apache.ibatis.logging.Log;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.spi.AbstractLogger;
//Log4j2Impl :相當於適配器
//Log :相當於源介面
public class Log4j2Impl implements Log {

  private Log log;
  //構造器
  public Log4j2Impl(String clazz) {
    //目標介面
    Logger logger = LogManager.getLogger(clazz);
    //判斷類型去實現:相當於目標
    if (logger instanceof AbstractLogger) {
      log = new Log4j2AbstractLoggerImpl((AbstractLogger) logger);
    } else {
      //源=目標
      log = new Log4j2LoggerImpl(logger);
    }
  }

目標介面:Logger

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2022最新版)

2.勁爆!Java 協程要來了。。。

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!

5.《Java開發手冊(嵩山版)》最新發佈,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!


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

-Advertisement-
Play Games
更多相關文章
  • 學習筆記 ant_vue模態框拖拽記錄 通過自定義命令 utils文件夾中新建dragModal.js import Vue from 'vue' // 註冊自定義拖拽指令,彌補 modal 組件不能拖動的缺陷 Vue.directive('drag-modal', (el, bindings, v ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 簡單介紹 Vue Router Vue Router 是 Vue.js 官方的路由插件,它和 Vue.js 是深度集成的,適合用於構建單頁面應用。vue的單頁面應用是基於路由和組件的,路由用於設定訪問路徑,並將路徑和組件映射起來。傳統的頁 ...
  • 黑夜模式 作為一個前端學習者,自然懂得黑夜模式的重要性,可惜主題原生未提供,那就自己弄吧 個人博客作為效果參考:https://jieniyou.github.io/ 設置基礎樣式 參考其他優秀產品的黑夜模式,得出共性: 那就是黑夜模式的背景一般不會是純黑(#000);而是淡黑色,字體也不是純白(# ...
  • 文章開始之前,我給大家推薦一個人工智慧學習網站,首先說我之前是完全不涉及人工智慧領域的,但是我盡然看懂了,以後老哥我就要參與人工智慧了。如果你也想學習,點擊跳轉到網站 最近打算寫一個用於股票體檢的軟體,比如股權質押比過高的股票不合格,ROE小於10的股票不合格,PE大於80的股票不合格等等等等,就像 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • MySQL主從同步是基於Bin Log實現的,而Bin Log記錄的是原始SQL語句。 Bin Log共有三種日誌格式,可以binlog_format配置參數指定。 ...
  • 歡迎關註公眾號:bin的技術小屋,如果大家在看文章的時候發現圖片載入不了,可以到公眾號查看原文 本系列Netty源碼解析文章基於 4.1.56.Final版本 最近在 Review Netty 代碼的時候,不小心用我的肉眼抓到了一個隱藏很深很深的記憶體泄露 Bug。 於是筆者將這個故事....哦不 . ...
  • 這兩篇的mvc都是一些開發多的註解呀和一些配置的問題,只需要記住一些該有的註解,它們的使用跟Servlet是十分相似的,還有ssm整合和springboot了,整體來說我寫的代碼都很少很多都是直接抄的代碼,主要是要去瞭解這些控制項,始終要記得的是ioc開發模式很多東西都是屬於是bean ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...