亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java設(shè)計模式之適配器模式

 更新時間:2022年10月11日 09:07:42   作者:tianClassmate  
這篇文章介紹了Java設(shè)計模式之適配器模式,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

本文通過老王使用紙質(zhì)書籍閱讀小王使用電子書籍的故事,詳細(xì)說明設(shè)計模式中的結(jié)構(gòu)型設(shè)計模式之適配器模式,分別對對象適配器和類適配器代碼實現(xiàn),最后為了加深理解,會列舉適配器設(shè)計模式在JDK和Spring源碼中的應(yīng)用。

讀者可以拉取完整代碼到本地進(jìn)行學(xué)習(xí),實現(xiàn)代碼均測試通過后上傳到碼云,本地源碼下載。

一、引出問題

自從小王被老王趕出家門以后,老王過了幾天舒心的日子,在家里的書架上買了許許多多的紙質(zhì)書。

有一天,小王過夠了野人生活回來了,小王也是一個喜歡讀書的人,但是小王不喜歡紙質(zhì)書,就要求老王將這些書換成電子版。

老王立馬就不開心了,這是我不知道花費多少個日夜才設(shè)計好的書架,給你換成電子版的不僅要花費我大量的精力改變原有書架的結(jié)構(gòu),再想找我想看的書得有多難,而且老李來了想看紙質(zhì)版怎么辦,我還要再換回去嗎?

小王隨即想到了一種解決思路:這些書現(xiàn)在符合你的風(fēng)格,應(yīng)該設(shè)計一種模式,讓這些書也能符合我的需求,讓我們倆可以在一起讀書,既不改變你的書架結(jié)構(gòu),又能擴(kuò)展它的功能。

老王滿意的點了點頭,你說的不錯,這實際上就是結(jié)構(gòu)型設(shè)計模式中的適配器模式。

二、概念與使用

引用Gof中對適配器設(shè)計模式的概念:將一個類的接口轉(zhuǎn)化成客戶希望的另一個接口,由于接口不兼容而不能一起工作的類可以一起工作。

很顯然,在適配器設(shè)計模式中應(yīng)該有三個角色。

目標(biāo)類:Target,該角色把其他類轉(zhuǎn)換為我們期望的接口,可以是一個抽象類或接口,也可以是具體類。
被適配者類(源): Adaptee ,原有的接口,也是希望被適配的接口。
適配器: Adapter, 將被適配者和目標(biāo)抽象類組合到一起的類。

在我們的實際案例中,老王的紙質(zhì)書很明顯應(yīng)該是屬于被適配者,小王的電子版就是目標(biāo)類,適配器應(yīng)該是能調(diào)用老王的紙質(zhì)書,并使用一些相關(guān)的業(yè)務(wù)方法轉(zhuǎn)化成電子版,比如調(diào)用老王書之前買一個掃描儀,在老王書調(diào)出來以后掃描書籍。

既然適配器中要調(diào)用老王的紙質(zhì)書,調(diào)用它的方法應(yīng)該是有兩種實現(xiàn)方式。

一是直接繼承老王,那樣就可以直接調(diào)用老王的方法了。

二是在適配器中創(chuàng)建老王的對象,然后再調(diào)用老王的方法。

這其實對應(yīng)了適配器的兩種方式,根據(jù)適配器類與適配者類的關(guān)系不同,適配器模式可分為對象適配器和類適配器兩種,在對象適配器模式中,適配器與適配者之間是關(guān)聯(lián)關(guān)系;在類適配器模式中,適配器與適配者之間是繼承(或?qū)崿F(xiàn))關(guān)系。

我們先看類適配器實現(xiàn)方式:

被適配者類:

/**
 * 源對象
 * @author tcy
 * @Date 04-08-2022
 */
public class AdapteePaperReading {

    public void readPaper(){
        System.out.println("這是老王讀的紙質(zhì)書...(被適配者方法)");
    }
}

目標(biāo)對象:

/**
 * 目標(biāo)對象
 */
public interface TargetOnlineReading {
    public void ReadOnline();
}

適配器:

/**
 * @author tcy
 * @Date 04-08-2022
 */
public class Adapter extends AdapteePaperReading implements TargetOnlineReading{
    @Override
    public void ReadOnline() {

        System.out.println("買一個掃描儀...");
        readPaper();
        System.out.println("拿到紙質(zhì)書掃描為電子書...");
    }
}

客戶端:

/**
 * @author tcy
 * @Date 04-08-2022
 */
public class Client {

    public static void main(String[] args) {
        Adapter adapter=new Adapter();
        adapter.ReadOnline();

    }
}

以上就實現(xiàn)類適配器,如果我們要實現(xiàn)對象適配器也很簡單,目標(biāo)對象和被適配者都不變,需要改變的是適配器代碼

/**
 * @author tcy
 * @Date 04-08-2022
 */
public class Adapter implements TargetOnlineReading {

    // 適配者是對象適配器的一個屬性
    private AdapteePaperReading adaptee = new AdapteePaperReading();

    @Override
    public void ReadOnline() {

        System.out.println("買一個掃描儀...");
        adaptee.readPaper();
        System.out.println("拿到紙質(zhì)書掃描為電子書...");
    }
}

這樣老王和小王就能在一起讀書了。但這種方式只能作為系統(tǒng)的一種補(bǔ)救措施,而不是在系統(tǒng)設(shè)計之初就考慮這種方式,如果老王有十個八個兒子都要求按照他們的習(xí)慣來,那系統(tǒng)就會相當(dāng)?shù)膹?fù)雜,無異于一場災(zāi)難。而是應(yīng)該考慮重做書架,將各種情況都考慮進(jìn)去。

需要說明的是,類適配器之間的耦合度比后者高,且要求程序員了解現(xiàn)有組件庫中的相關(guān)組件的內(nèi)部結(jié)構(gòu),所以應(yīng)用相對較少些。

三、應(yīng)用

案例有一些生硬,為了加深對適配器設(shè)計模式的把握,我們介紹該模式在Jdk源碼和Spring中的應(yīng)用。

1、JDK應(yīng)用

JDK使用適配器的典型例子是Java線程池FutureTask類。我們知道通過實現(xiàn)接口實現(xiàn)多線程一共有兩種方式,Runnable接口和Callable接口。

FutrueTask類中有兩個構(gòu)造方法:

構(gòu)造方法一:傳入?yún)?shù)為Callable接口

// 這是FutureTask的構(gòu)造方法一
public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;     
}

構(gòu)造方法二:傳入的參數(shù)為Runnable接口

// 這是FutureTask的構(gòu)造方法二
public FutureTask(Runnable runnable, V result) {
	// 調(diào)用Executors類中的callable方法進(jìn)行轉(zhuǎn)化
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;   
}

在構(gòu)造方法中實際上加傳入的Runnable任務(wù)在內(nèi)部統(tǒng)一被轉(zhuǎn)換為Callable任務(wù)。

可以看到這里采用的是適配器模式,調(diào)用RunnableAdapter<T>(task, result)方法來適配,實現(xiàn)如下:

static final class RunnableAdapter<T> implements Callable<T> {
    final Runnable task;
    final T result;
    RunnableAdapter(Runnable task, T result) {
        this.task = task;
        this.result = result;
    }
    public T call() {
        task.run();
        return result;
    }
}

這樣無論是傳入Runnalbe還是Callable都能適配任務(wù),這個適配器很簡單,就是簡單的實現(xiàn)了Callable接口,在call()實現(xiàn)中調(diào)用Runnable.run()方法,然后把傳入的result作為任務(wù)的結(jié)果返回。

通過這么一個簡單案例可以加深對適配器模式的理解。

2、SpringAOP應(yīng)用

我們知道在Spring的Aop中,使用的 Advice(通知) 來增強(qiáng)被代理類的功能。

其中Advice的類型有:BeforeAdvice(在執(zhí)行切點前的通知)、AfterReturningAdvice(在運行完切點完未返回之前)、ThrowsAdvice(在運行完切點時拋出異常進(jìn)行的通知),AfterAdvice(執(zhí)行完該切點后,進(jìn)行的通知)、Around advice(包裹一個方法的執(zhí)行)

在每個類型 Advice 都有對應(yīng)的攔截器,MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、 ThrowsAdviceInterceptor

Spring需要將每個 Advice 都封裝成對應(yīng)的攔截器類型,返回給容器,這時候采用的就是適配器類型。

Advice 就相當(dāng)于適配者,對應(yīng)的攔截器類型就是目標(biāo)類。

3、SpringMVC應(yīng)用

Spring MVC中的適配器模式主要用于執(zhí)行目標(biāo) Controller 中的請求處理方法。

在Spring MVC中,DispatcherServlet 作為用戶,HandlerAdapter 作為期望接口,具體的適配器實現(xiàn)類用于對目標(biāo)類進(jìn)行適配,Controller 作為需要適配的類。

當(dāng)Spring容器啟動后,會將所有定義好的適配器對象存放在一個List集合中,當(dāng)一個請求來臨時,DispatcherServlet 會通過 handler 的類型找到對應(yīng)適配器,并將該適配器對象返回給用戶,然后就可以統(tǒng)一通過適配器的 hanle() 方法來調(diào)用 Controller 中的用于處理請求的方法。

通過適配器模式我們將所有的 controller 統(tǒng)一交給 HandlerAdapter 處理,免去了寫大量的 if-else 語句對 Controller 進(jìn)行判斷,也更利于擴(kuò)展新的 Controller 類型。

單純的說蒼白無力,我們手寫實現(xiàn)SpringMVC的核心流程,完整代碼已經(jīng)上傳到碼云。

四、總結(jié)

既然適配器模式可以擴(kuò)展原有類的功能,那它和代理模式在一定程度上不是重合了嗎?貌似擴(kuò)展老王的書架使用代理模式同樣是可以實現(xiàn)。

其實我們看結(jié)構(gòu)型設(shè)計模式的定義:結(jié)構(gòu)型模式涉及到如何組合類和類以獲得更大的結(jié)構(gòu),結(jié)構(gòu)型類模式采用繼承機(jī)制來組合接口或?qū)崿F(xiàn)。

代理模式與適配器模式都分別有繼承、接口方式實現(xiàn)的子分類模式?;诮涌趯崿F(xiàn)的代理模式稱為靜態(tài)代理模式、JDK(動態(tài))代理模式,基于繼承實現(xiàn)的代理模式稱為Cglib(動態(tài))代理模式。

基于接口(同時含類繼承)實現(xiàn)的適配器模式稱為類適配器模式,(只)基于繼承(使用委托)實現(xiàn)的適配器模式稱為類適配器模式。

代理模式是為其他類提供一種代理以控制對這個類的訪問。我們不直接去接觸目標(biāo)類,而是直接操作代理類,代理類再去操作目標(biāo)類。因為不直接接觸目標(biāo)類,因此我們可以在代理類的同名方法中添加或刪除功能模塊,而不用去修改目標(biāo)類的原方法。

而適配器模式則主要是協(xié)調(diào)現(xiàn)實與需求的差異,減少對已有代碼的改動,適配不同的接口、類類型。

項目實施中可能會出現(xiàn)這樣的情況:當(dāng)前已完成的項目的某一個包內(nèi)的各個類實現(xiàn)了一些特定的接口,而客戶提出了新的需求,要求實現(xiàn)他所指定的那些接口(拋棄原有的方法或接口),但其業(yè)務(wù)細(xì)節(jié)卻是相同、完全一樣的。此時,我們可能并不想復(fù)制粘貼原代碼到新的方法中去,這就需要將一個類的接口轉(zhuǎn)換成新需求的另一個接口。

實現(xiàn)方式有很多,沒有必要咬文嚼字糾結(jié)使用哪種設(shè)計模式,設(shè)計模式本身就是很相似,只要能簡潔開發(fā)流程,讓我們的代碼更好的工作就是完美的。具體使用哪一種就需要讀者熟練掌握各種設(shè)計模式了,并認(rèn)真體會他們各自的優(yōu)勢。

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接

相關(guān)文章

  • Java8 Lambda表達(dá)式詳解及實例

    Java8 Lambda表達(dá)式詳解及實例

    這篇文章主要介紹了Java8 Lambda表達(dá)式詳解的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • spring boot(四)之thymeleaf使用詳解

    spring boot(四)之thymeleaf使用詳解

    Thymeleaf 是一個跟 Velocity、FreeMarker 類似的模板引擎,它可以完全替代 JSP 。接下來通過本文給大家介紹spring boot(四)之thymeleaf使用詳解,需要的朋友可以參考下
    2017-05-05
  • Java集合Set的簡單使用解析

    Java集合Set的簡單使用解析

    這篇文章主要介紹了Java集合Set的簡單使用解析,Set接口是Collection的子接口,Set接口相較于Collection接口沒有提供額外的方法,Set 集合不允許包含相同的元素,如果試把兩個相同的元素加入同一個 Set 集合中,則添加操作失敗,需要的朋友可以參考下
    2023-11-11
  • Java 基礎(chǔ)--Arrays工具類詳解

    Java 基礎(chǔ)--Arrays工具類詳解

    這篇文章主要介紹了Java Arrays工具類用法,結(jié)合實例形式分析了java Arrays工具類針對數(shù)組元素修改、復(fù)制、排序等操作使用技巧與相關(guān)注意事項,需要的朋友可以參考下
    2021-09-09
  • mybatis的foreach標(biāo)簽語法報錯的解決

    mybatis的foreach標(biāo)簽語法報錯的解決

    這篇文章主要介紹了mybatis的foreach標(biāo)簽語法報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • druid監(jiān)控?zé)o法關(guān)閉的坑以及處理方式

    druid監(jiān)控?zé)o法關(guān)閉的坑以及處理方式

    這篇文章主要介紹了druid監(jiān)控?zé)o法關(guān)閉的坑以及處理方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 詳解spring cloud整合Swagger2構(gòu)建RESTful服務(wù)的APIs

    詳解spring cloud整合Swagger2構(gòu)建RESTful服務(wù)的APIs

    這篇文章主要介紹了詳解spring cloud整合Swagger2構(gòu)建RESTful服務(wù)的APIs,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • 如何使用java.security.SecureRandom安全生成隨機(jī)數(shù)和隨機(jī)字符串工具類

    如何使用java.security.SecureRandom安全生成隨機(jī)數(shù)和隨機(jī)字符串工具類

    這篇文章主要給大家介紹了關(guān)于如何使用java.security.SecureRandom安全生成隨機(jī)數(shù)和隨機(jī)字符串工具類的相關(guān)資料,SecureRandom擴(kuò)展了Random類,并通過在java 8中添加的新方法得到了豐富,需要的朋友可以參考下
    2024-05-05
  • IntelliJ IDEA 15款超級牛逼插件推薦(自用,超級牛逼)

    IntelliJ IDEA 15款超級牛逼插件推薦(自用,超級牛逼)

    這篇文章主要給大家推薦介紹了IntelliJ IDEA 15款超級牛逼插件,這15款插件都是自用的,真的非常推薦,需要的朋友可以參考下
    2020-11-11
  • java實現(xiàn)砸金蛋抽獎功能

    java實現(xiàn)砸金蛋抽獎功能

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)砸金蛋抽獎功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11

最新評論