国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

一起學設計模式 - 適配器模式

codeKK / 2532人閱讀

摘要:建議盡量使用對象的適配器模式,少用繼承。適配器模式也是一種包裝模式,它與裝飾模式同樣具有包裝的功能,此外,對象適配器模式還具有委托的意思。

適配器模式(Adapter Pattern)屬于結構型模式的一種,把一個類的接口變成客戶端所期待的另一種接口,從而使原本接口不匹配而無法一起工作的兩個類能夠在一起工作...

概述

當你想使用一個已經存在的類,而它的接口不符合你的需求,或者你想創建一個可重用的類(與不兼容接口無關的類),這時候可以考慮使用適配器模式。同時它也是一種包裝模式,它與裝飾模式同樣具有包裝的功能。

案例

筆者算是小米的忠實用戶了,從大學期間起至今都是購買的小米,期間發現小米5在推出的時候,它會送一個type-c的轉接口給我們,那會type-c數據線應該還不算普及,這種做法還是蠻好的,在使用轉接口后Micro USB得以重復利用,這樣一來即使原裝的米5數據線丟了也沒關系,只要有type-c轉接口,一樣可以用Micro USB充電/連接電腦

類適配器

1.首先定義M4DataLine 代表是Micro USB,我們目的就是通過適配器能夠用米4數據線連接米5手機

class M4DataLine {
    public void connection() {
        System.out.println("使用小米4數據線連接...");
    }
}

2.定義客戶端使用的接口,與業務相關

interface Target {
    void connection();
}

class M5DataLine implements Target {
    @Override
    public void connection() {
        System.out.println("使用小米5數據線連接...");
    }
}

3.創建適配器類,繼承了被適配類,同時實現標準接口

class M5DataLineAdapter extends M4DataLine implements Target {

    @Override
    public void connection() {
        System.out.println("插入 type-c 轉接頭");
        super.connection();
    }
}

4.客戶端代碼,測試

public class AdapterMain {

    public static void main(String[] args) {
        Target target = new M5DataLine();
        target.connection();

        Target adapter = new M5DataLineAdapter();
        adapter.connection();
    }
}

5.結果

使用小米5數據線連接...
插入 type-c 轉接頭
使用小米4數據線連接...
對象適配器

創建適配器類,實現標準接口,將這個調用委托給實現新接口的對象來處理

class M5DataLineAdapter implements Target {

    private Target target;

    public M5DataLineAdapter(Target target) {
        this.target = target;
    }

    @Override
    public void connection() {
        System.out.println("插入 type-c 轉接頭");
        target.connection();
    }
}

public class AdapterMain {

    public static void main(String[] args) {
        // 使用特殊功能類,即適配類
        Target adapter = new M5DataLineAdapter(new M5DataLine());
        adapter.connection();
    }
}
區別

類適配器:對象繼承的方式,靜態的定義。

對象適配器:依賴于對象的組合,都是采用對象組合的方式,也就是對象適配器實現的方式。

JDK 中的適配器使用

使用適配器模式的類

java.util.Arrays#asList()
java.io.InputStreamReader(InputStream)
java.io.OutputStreamWriter(OutputStream)

Java I/O 庫大量使用了適配器模式,如 ByteArrayInputStream 是一個適配器類,它繼承了 InputStream 的接口,并且封裝了一個 byte 數組。換言之,它將一個 byte 數組的接口適配成 InputStream 流處理器的接口。

OutputStream 類型中,所有的原始流處理器都是適配器類。ByteArrayOutputStream 繼承了 OutputStream 類型,同時持有一個對 byte 數組的引用。它一個 byte 數組的接口適配成 OutputString 類型的接口,因此也是一個對象形式的適配器模式的應用。

FileOutputStream 繼承了 OutputStream 類型,同時持有一個對 FileDiscriptor 對象的引用。這是一個將 FileDiscriptor 接口適配成 OutputStream 接口形式的對象型適配器模式。

Reader 類型的原始流處理器都是適配器模式的應用。StringReader 是一個適配器類,StringReader 類繼承了 Reader 類型,持有一個對 String 對象的引用。它將 String 的接口適配成 Reader 類型的接口。

Spring 中使用適配器模式的典型應用

在 Spring 的 AOP 里通過使用的 Advice(通知)來增強被代理類的功能。Spring 實現這一 AOP 功能的原理就使用代理模式(1、JDK 動態代理。2、CGLib 字節碼生成技術代理。)對類進行方法級別的切面增強,即,生成被代理類的代理類,并在代理類的方法前,設置攔截器,通過執行攔截器中的內容增強了代理方法的功能,實現的面向切面編程。

Advice(通知)的類型有:BeforeAdvice、AfterReturningAdvice、ThrowSadvice 等。每個類型 Advice(通知)都有對應的攔截器,MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor。Spring 需要將每個 Advice(通知)都封裝成對應的攔截器類型,返回給容器,所以需要使用適配器模式對 Advice 進行轉換。

public interface MethodBeforeAdvice extends BeforeAdvice {
    void before(Method method, Object[] args, Object target) throws Throwable;
}

public interface AdvisorAdapter {

    boolean supportsAdvice(Advice advice);

    MethodInterceptor getInterceptor(Advisor advisor);
}

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

    @Override
    public boolean supportsAdvice(Advice advice) {
        return (advice instanceof MethodBeforeAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }

}

默認的適配器注冊表

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

    private final List adapters = new ArrayList(3);

    public DefaultAdvisorAdapterRegistry() {
        // 注冊適配器 
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
        if (!(adviceObject instanceof Advice)) {
            throw new UnknownAdviceTypeException(adviceObject);
        }
        Advice advice = (Advice) adviceObject;
        if (advice instanceof MethodInterceptor) {
            // So well-known it doesn"t even need an adapter.
            return new DefaultPointcutAdvisor(advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
            // 檢查是否支持,這里調用了適配器的方法 
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

    @Override
    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List interceptors = new ArrayList(3);
        Advice advice = advisor.getAdvice();
        if (advice instanceof MethodInterceptor) {
            interceptors.add((MethodInterceptor) advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
            // 檢查是否支持,這里調用了適配器的方法 
            if (adapter.supportsAdvice(advice)) {
                interceptors.add(adapter.getInterceptor(advisor));
            }
        }
        if (interceptors.isEmpty()) {
            throw new UnknownAdviceTypeException(advisor.getAdvice());
        }
        return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
    }

    @Override
    public void registerAdvisorAdapter(AdvisorAdapter adapter) {
        this.adapters.add(adapter);
    }

}
總結

優點

可以讓任何兩個沒有關聯的類一起運行

提高了類的復用,想使用現有的類,而此類的接口標準又不符合現有系統的需要。通過適配器模式就可以讓這些功能得到更好的復用。

增加了類的透明度,客戶端只關注結果

使用適配器的時候,可以調用自己開發的功能,從而自然地擴展系統的功能。

缺點

過多使用會導致系統凌亂,追溯困難(內部轉發導致,調用A適配成B)

適用場景

系統需要使用一些現有的類,而這些類的接口(如方法名)不符合系統的需要,甚至沒有這些類的源代碼。

想創建一個可以重復使用的類,用于與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作。

小故事

魏文王問名醫扁鵲說:“你們家兄弟三人,都精于醫術,到底哪一位最好呢?”
扁鵲答:“大哥最好,二哥次之,我最差。”
文王再問:“那么為什么你最出名呢?”
扁鵲答說:“我大哥治病,是治病于病情發作之前。由于一般人不知道他率先能鏟除病因,所以他的名氣無法傳出去,只有我們家的人才知道。我二哥治病,是治病于病情初起之時。一般人以為他只能治輕微的小病,所以他的名氣只及于本鄉里。而我扁鵲治病,是治病于病情嚴重之時。一般人都看到我在經脈上穿針管來放血、在皮膚上敷藥等大手術,所以以為我的醫術高明,名氣因此響遍全國。”
比較起來,能防范于未然是最高明的,但往往因防范在前,不會出現惡果,使事物保持了原態,沒有“明顯”的功績而被忽略。正如不見防火英雄,只有救火英雄一樣。高明者不見得一定名聲顯赫。

建議盡量使用對象的適配器模式,少用繼承。適配器模式也是一種包裝模式,它與裝飾模式同樣具有包裝的功能,此外,對象適配器模式還具有委托的意思。總的來說,適配器模式屬于補償模式,專門用來在系統后期擴展、修改時使用,但要注意不要過度使用適配器模式。

參考文獻:《大話設計模式》

IBM developerWorks:適配器模式原理及實例介紹

- 說點什么

全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter5/battcn-adapter

個人QQ:1837307557

battcn開源群(適合新手):391619659

微信公眾號:battcn(歡迎調戲)

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67949.html

相關文章

  • 一起設計模式 - 外觀模式

    摘要:適配器是將接口轉換為不同接口,而外觀模式是提供一個統一的接口來簡化接口。 外觀模式(Facade Pattern)屬于結構型模式的一種,為子系統中的一組接口提供一個統一的入口,它通過引入一個外觀角色來簡化客戶端與子系統之間的交互... 概述 外觀模式是一種使用頻率非常高的結構型設計模式,當你要為一個復雜子系統提供一個簡單接口時。子系統往往因為不斷演化而變得越來越復雜。大多數模式使用時...

    zone 評論0 收藏0
  • 互聯網常用設計模式——通往架構師的第一步

    摘要:設計模式的分類經典應用框架中常見的設計模式分為三類創建型模式對類的實例化過程的抽象。對象的結構模式是動態的。對象的行為模式則使用對象的聚合來分配行為。設計模式是個好東西,以后肯定還要進一步的學習,并且在項目中多實踐,提升自己的設計能力。 什么是設計模式? Christopher Alexander?說過:每一個模式描述了一個在我們周圍不斷重復發生的問題,以及該問題的解決方案的核心。這樣...

    張紅新 評論0 收藏0
  • java 基礎 - 收藏集 - 掘金

    摘要:基礎知識復習后端掘金的作用表示靜態修飾符,使用修飾的變量,在中分配內存后一直存在,直到程序退出才釋放空間。將對象編碼為字節流稱之為序列化,反之將字節流重建成對象稱之為反序列化。 Java 學習過程|完整思維導圖 - 后端 - 掘金JVM 1. 內存模型( 內存分為幾部分? 堆溢出、棧溢出原因及實例?線上如何排查?) 2. 類加載機制 3. 垃圾回收 Java基礎 什么是接口?什么是抽象...

    makeFoxPlay 評論0 收藏0
  • java篇 - 收藏集 - 掘金

    摘要:進階多線程開發關鍵技術后端掘金原創文章,轉載請務必將下面這段話置于文章開頭處保留超鏈接。關于中間件入門教程后端掘金前言中間件 Java 開發人員最常犯的 10 個錯誤 - 后端 - 掘金一 、把數組轉成ArrayList 為了將數組轉換為ArrayList,開發者經常... Java 9 中的 9 個新特性 - 后端 - 掘金Java 8 發布三年多之后,即將快到2017年7月下一個版...

    OpenDigg 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<