設(shè)計(jì)模式學(xué)習(xí)08(Java實(shí)現(xiàn))——適配器模式

寫在前面

  • 記錄學(xué)習(xí)設(shè)計(jì)模式的筆記
  • 提高對(duì)設(shè)計(jì)模式的靈活運(yùn)用

學(xué)習(xí)地址

https://www.bilibili.com/video/BV1G4411c7N4

https://www.bilibili.com/video/BV1Np4y1z7BU

參考文章

http://c.biancheng.net/view/1317.html

項(xiàng)目源碼
https://gitee.com/zhuang-kang/DesignPattern

10,適配器模式

10.1 適配器模式的定義和特點(diǎn)

適配器模式(Adapter)的定義如下:將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口,使得原本由于接口不兼容而不能一起工作的那些類能一起工作。適配器模式分為類結(jié)構(gòu)型模式和對(duì)象結(jié)構(gòu)型模式兩種,前者類之間的耦合度比后者高。

該模式的主要優(yōu)點(diǎn)如下:

  • 客戶端通過適配器可以透明地調(diào)用目標(biāo)接口。
  • 復(fù)用了現(xiàn)存的類,程序員不需要修改原有代碼而重用現(xiàn)有的適配者類。
  • 將目標(biāo)類和適配者類解耦,解決了目標(biāo)類和適配者類接口不一致的問題。
  • 在很多業(yè)務(wù)場(chǎng)景中符合開閉原則。

其缺點(diǎn)是:

  • 適配器編寫過程需要結(jié)合業(yè)務(wù)場(chǎng)景全面考慮,可能會(huì)增加系統(tǒng)的復(fù)雜性。
  • 增加代碼閱讀難度,降低代碼可讀性,過多使用適配器會(huì)使系統(tǒng)代碼變得凌亂。

10.2 適配器模式的結(jié)構(gòu)與實(shí)現(xiàn)

10.2.1 適配器模式的結(jié)構(gòu)

  1. 目標(biāo)(Target)接口:當(dāng)前系統(tǒng)業(yè)務(wù)所期待的接口,它可以是抽象類或接口。
  2. 適配者(Adaptee)類:它是被訪問和適配的現(xiàn)存組件庫中的組件接口。
  3. 適配器(Adapter)類:它是一個(gè)轉(zhuǎn)換器,通過繼承或引用適配者的對(duì)象,把適配者接口轉(zhuǎn)換成目標(biāo)接口,讓客戶按目標(biāo)接口的格式訪問適配者。

10.2.2 代碼實(shí)現(xiàn)

10.2.2.1 類適配器模式

Voltage5V 目標(biāo)接口

package com.zhuang.adapter.classadapter;

/**
 * @Classname Voltage5V
 * @Description  定義直流電
 * @Date 2021/3/21 14:14
 * @Created by dell
 */

public interface Voltage5V {
    //定義一個(gè)標(biāo)準(zhǔn)充電器來實(shí)現(xiàn)
    public int output5V();
}

Voltage220V

package com.zhuang.adapter.classadapter;

/**
 * @Classname Voltage220V
 * @Description 創(chuàng)建交流電
 * @Date 2021/3/21 14:13
 * @Created by dell
 */

public class Voltage220V {
    public int output220V() {
        System.out.println("voltage 輸出220伏");
        return 220;
    }
}

VoltageAdapter

package com.zhuang.adapter.classadapter;

/**
 * @Classname VoltageAdapter
 * @Description 創(chuàng)建充電器
 * @Date 2021/3/21 14:14
 * @Created by dell
 */

public class VoltageAdapter extends Voltage220V implements Voltage5V {
    @Override
    public int output5V() {
        //獲取交流電220V
        int output220V = output220V();
        //轉(zhuǎn)為5V
        int output5V = output220V / 44;
        System.out.println("VoltageAdapter 輸出5伏");
        return output5V;
    }
}

Phone

package com.zhuang.adapter.classadapter;

/**
 * @Classname Phone
 * @Description 手機(jī)類
 * @Date 2021/3/21 14:15
 * @Created by dell
 */

public class Phone {
    public void charging(Voltage5V voltage5V) {
        if (voltage5V.output5V() == 5) {
            System.out.println("電壓5伏,可以充電");
        } else if (voltage5V.output5V() > 5) {
            System.out.println("電壓過大,不可以充電");
        }
    }
}

Client

package com.zhuang.adapter.classadapter;

/**
 * @Classname Client
 * @Description  客戶端類
 * @Date 2021/3/21 14:15
 * @Created by dell
 */

public class Client {
    public static void main(String[] args) {
        System.out.println("==類適配器==");
        Phone phone = new Phone();
        phone.charging(new VoltageAdapter());
    }
}
image

類適配器模式注意事項(xiàng)和細(xì)節(jié)

  • Java是單繼承機(jī)制,所以類適配器需要繼承適配者(Adaptee,指Voltage220V)類,這點(diǎn)算是一個(gè)缺點(diǎn),除此之外還必須要求目標(biāo)(Target,指Voltage5V)必須是接口,有一定局限性;
  • 適配者Voltage220V類的方法在適配器VoltageAdapter類中都會(huì)暴露出來,也增加了使用的成本。但是由于其繼承了適配者Voltage220V類,所以它可以根據(jù)需求重寫該類的方法,使得適配器VoltageAdapter類的靈活性增強(qiáng)了。

10.2.2.2 對(duì)象適配器模式

Voltage5V

package com.zhuang.adapter.objectadapter;

/**
 * @Classname Voltage5V
 * @Description 充電5V
 * @Date 2021/3/21 14:32
 * @Created by dell
 */

public interface Voltage5V {
    //定義一個(gè)標(biāo)準(zhǔn)充電器來實(shí)現(xiàn)
    public int output5V();
}

Voltage220V

package com.zhuang.adapter.objectadapter;

/**
 * @Classname Voltage220V
 * @Description 輸出220V類
 * @Date 2021/3/21 14:32
 * @Created by dell
 */

public class Voltage220V {
    public int output220V() {
        System.out.println("voltage 輸出220伏");
        return 220;
    }
}

VoltageAdapter

package com.zhuang.adapter.objectadapter;

/**
 * @Classname VoltageAdapter
 * @Description 適配器類
 * @Date 2021/3/21 14:33
 * @Created by dell
 */

public class VoltageAdapter implements Voltage5V {

    private Voltage220V voltage220V;

    public VoltageAdapter(Voltage220V voltage220V) {
        this.voltage220V = voltage220V;
    }

    @Override
    public int output5V() {
        //獲取交流電220V
        int output220V = voltage220V.output220V();
        //轉(zhuǎn)為5V
        int output5V = output220V / 44;
        System.out.println("VoltageAdapter 輸出5伏");
        return output5V;
    }
}

Phone

package com.zhuang.adapter.objectadapter;

/**
 * @Classname Phone
 * @Description 手機(jī)類
 * @Date 2021/3/21 14:33
 * @Created by dell
 */

public class Phone {
    public void charging(Voltage5V voltage5V) {
        if (voltage5V.output5V() == 5) {
            System.out.println("電壓5伏,可以充電");
        } else if (voltage5V.output5V() > 5) {
            System.out.println("電壓過大,不可以充電");
        }
    }
}

Client

package com.zhuang.adapter.objectadapter;

/**
 * @Classname Client
 * @Description 對(duì)象適配器測(cè)試類
 * @Date 2021/3/21 14:33
 * @Created by dell
 */

public class Client {

    public static void main(String[] args) {
        System.out.println("==對(duì)象適配器==");
        Phone phone = new Phone();
        phone.charging(new VoltageAdapter(new Voltage220V()));
    }
}
image

對(duì)象適配器模式注意事項(xiàng)和細(xì)節(jié)

  • 對(duì)象適配器和類適配器其實(shí)算是同一種思想,只不過實(shí)現(xiàn)方式不同。

  • 根據(jù)合成復(fù)用原則,使用組合替代繼承, 所以它解決了類適配器中VoltageAdapter必須繼承Voltage220V的局限性問題,也不再?gòu)?qiáng)制要求Voltage5V必須是接口。使用成本更低,更靈活。因此,對(duì)象適配器模式是適配器模式常用的一種。

10.2.2.3 接口適配器模式

Animation

package com.zhuang.adapter.interfaceadapter;

/**
 * @Classname Animation
 * @Description 動(dòng)畫接口
 * @Date 2021/3/21 14:47
 * @Created by dell
 */

public interface Animation {
    public void method1();

    public void method2();

    public void method3();

    public void method4();

    public void method5();
}

AnimationAdapter

package com.zhuang.adapter.interfaceadapter;

/**
 * @Classname AnimationAdapter
 * @Description  接口適配器類
 * @Date 2021/3/21 14:48
 * @Created by dell
 */

public class AnimationAdapter implements Animation {
    //全部都空實(shí)現(xiàn)
    @Override
    public void method1() {

    }

    @Override
    public void method2() {

    }

    @Override
    public void method3() {

    }

    @Override
    public void method4() {

    }

    @Override
    public void method5() {

    }
}

JFrameAnimation

package com.zhuang.adapter.interfaceadapter;

/**
 * @Classname JFrameAnimation
 * @Description 適配器子類
 * @Date 2021/3/21 14:49
 * @Created by dell
 */

public class JFrameAnimation extends AnimationAdapter {
    @Override
    public void method1() {
        System.out.println("method1()被調(diào)用了...");
    }

    @Override
    public void method2() {
        System.out.println("method2()被調(diào)用了...");
    }
}

Client

package com.zhuang.adapter.interfaceadapter;

/**
 * @Classname Client
 * @Description  客戶端類
 * @Date 2021/3/21 14:50
 * @Created by dell
 */

public class Client {
    public static void main(String[] args) {
        JFrameAnimation animation = new JFrameAnimation();
        animation.method1();
        animation.method2();
    }
}
image

10.3 SpringMVC源碼解析

Controller

package com.zhuang.adapter.springmvc;

/**
 * @Classname Controller
 * @Description  springmvc的Controller源碼
 * @Date 2021/3/21 14:53
 * @Created by dell
 */

//多種Controller實(shí)現(xiàn)
public interface Controller {

}

class HttpController implements Controller {
    public void doHttpHandler() {
        System.out.println("http...");
    }
}

class SimpleController implements Controller {
    public void doSimplerHandler() {
        System.out.println("simple...");
    }
}

class AnnotationController implements Controller {
    public void doAnnotationHandler() {
        System.out.println("annotation...");
    }
}

DispatchServlet

package com.zhuang.adapter.springmvc;

import java.util.ArrayList;
import java.util.List;

/**
 * @Classname DispatchServlet
 * @Description  springmvc的DispatchServlet源碼
 * @Date 2021/3/21 14:52
 * @Created by dell
 */

public class DispatchServlet {
    public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();

    public DispatchServlet() {
        handlerAdapters.add(new AnnotationHandlerAdapter());
        handlerAdapters.add(new HttpHandlerAdapter());
        handlerAdapters.add(new SimpleHandlerAdapter());
    }

    public void doDispatch() {

        // 此處模擬SpringMVC從request取handler的對(duì)象,
        // 適配器可以獲取到希望的Controller
        HttpController controller = new HttpController();
        // AnnotationController controller = new AnnotationController();
        //SimpleController controller = new SimpleController();
        // 得到對(duì)應(yīng)適配器
        HandlerAdapter adapter = getHandler(controller);
        // 通過適配器執(zhí)行對(duì)應(yīng)的controller對(duì)應(yīng)方法
        adapter.handle(controller);

    }

    public HandlerAdapter getHandler(Controller controller) {
        //遍歷:根據(jù)得到的controller(handler), 返回對(duì)應(yīng)適配器
        for (HandlerAdapter adapter : this.handlerAdapters) {
            if (adapter.supports(controller)) {
                return adapter;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        new DispatchServlet().doDispatch(); // http...
    }

}

HandlerAdapter

package com.zhuang.adapter.springmvc;

/**
 * @Classname HandlerAdapter
 * @Description  springmvc的HandlerAdapter源碼
 * @Date 2021/3/21 14:53
 * @Created by dell
 */

///定義一個(gè)Adapter接口
public interface HandlerAdapter {
    public boolean supports(Object handler);

    public void handle(Object handler);
}

// 多種適配器類

class SimpleHandlerAdapter implements HandlerAdapter {

    @Override
    public void handle(Object handler) {
        ((SimpleController) handler).doSimplerHandler();
    }

    @Override
    public boolean supports(Object handler) {
        return (handler instanceof SimpleController);
    }

}

class HttpHandlerAdapter implements HandlerAdapter {

    @Override
    public void handle(Object handler) {
        ((HttpController) handler).doHttpHandler();
    }

    @Override
    public boolean supports(Object handler) {
        return (handler instanceof HttpController);
    }

}

class AnnotationHandlerAdapter implements HandlerAdapter {

    @Override
    public void handle(Object handler) {
        ((AnnotationController) handler).doAnnotationHandler();
    }

    @Override
    public boolean supports(Object handler) {

        return (handler instanceof AnnotationController);
    }
}

image

寫在最后

  • 如果我的文章對(duì)你有用,請(qǐng)給我點(diǎn)個(gè)??,感謝你??!
  • 有問題,歡迎在評(píng)論區(qū)指出!??
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容