天天看點

23種設計模式之擴充卡模式1. 項目需求分析2. 什麼是擴充卡模式?3. 擴充卡模式的工作原理4. 類擴充卡5. 對象擴充卡6. 接口擴充卡模式7. 擴充卡在SpringMVC架構應用的源碼分析8. 手寫SpringMvc通過擴充卡設計模式擷取對應Controller的源碼。9. 擴充卡模式的注意事項和細節

文章目錄

  • 1. 項目需求分析
    • 1.1 顯示生活中的例子
  • 2. 什麼是擴充卡模式?
  • 3. 擴充卡模式的工作原理
  • 4. 類擴充卡
    • 4.1 類擴充卡基本介紹
    • 4.2 類擴充卡模式應用執行個體
    • 4.2 用類圖來描述
    • 4.3 上代碼
      • 4.3.1 被擴充卡類
      • 4.3.2 适配接口
      • 4.3.3 擴充卡類
      • 4.3.4 手機類,使用擴充卡
      • 4.3.5 測試類
      • 4.3.6 運作結果
    • 4.4 類擴充卡模式注意事項和細節
      • 4.4.1 缺點
      • 4.4.2 優點
  • 5. 對象擴充卡
    • 5.1 對象擴充卡模式介紹
    • 5.2 用類圖來描述
    • 5.3 上代碼
      • 5.3.1 改進擴充卡類
      • 5.3.2 修改測試類,其他類不變
      • 5.3.3 運作結果
    • 5.4 對象擴充卡模式注意事項和細節
  • 6. 接口擴充卡模式
    • 6.1 接口擴充卡模式介紹
    • 6.2 用類圖來描述
    • 6.3 上代碼
      • 6.3.1 接口
      • 6.3.2 抽象擴充卡,實作所有方法
      • 6.3.3 測試類
      • 6.3.4 運作結果
  • 7. 擴充卡在SpringMVC架構應用的源碼分析
    • 7.1 SpringMvc的HandlerAdapter,就使用了擴充卡模式。
      • 7.1.1 DispatcherServlet類
  • 8. 手寫SpringMvc通過擴充卡設計模式擷取對應Controller的源碼。
    • 8.1 用類圖來描述
    • 8.2 上代碼
      • 8.2.1 controller類
      • 8.2.2 擴充卡類
      • 8.2.3 DispatchServlet類
      • 8.2.4 運作結果
  • 9. 擴充卡模式的注意事項和細節

1. 項目需求分析

1.1 顯示生活中的例子

假如去泰國旅遊,泰國的插座都是兩孔的(歐标),而我們國家的插座但是三孔的,于是可以買個多功能轉換插頭(擴充卡),這樣就可以使用了。

2. 什麼是擴充卡模式?

  1. 擴充卡模式(Adapter Pattern)将某個類的接口轉換成用戶端期望的另一個接口表示,主要目的是相容性,讓原本因接口不比對而不能在一起工作的兩個類可以協同工作。其别名為包裝器(Wrapper)
  2. 擴充卡模式屬于結構型模式。
  3. 主要分為3類:擴充卡模式、對象擴充卡模式、接口擴充卡模式。

3. 擴充卡模式的工作原理

  1. 擴充卡模式:将一個類接口轉換成另一種接口,讓原本接口不相容的類可以相容。
  2. 從使用者的角度看不到被适配者,是解耦的。
  3. 使用者調用擴充卡轉化出來的目标接口方法,擴充卡再調用被适配者的相關接口方法。
  4. 使用者收到回報結果,感覺隻是和目标接口互動,如圖
    23種設計模式之擴充卡模式1. 項目需求分析2. 什麼是擴充卡模式?3. 擴充卡模式的工作原理4. 類擴充卡5. 對象擴充卡6. 接口擴充卡模式7. 擴充卡在SpringMVC架構應用的源碼分析8. 手寫SpringMvc通過擴充卡設計模式擷取對應Controller的源碼。9. 擴充卡模式的注意事項和細節

4. 類擴充卡

4.1 類擴充卡基本介紹

Adapter類,通過繼承src類,實作dst類接口,完成src->dst的适配。

4.2 類擴充卡模式應用執行個體

  1. 以生活中充電器的例子來講解擴充卡,充電器本身相當于Adapter,220V交流電相當于src(即被适配者),我們的dst(即 目标)是5V直流電。
    23種設計模式之擴充卡模式1. 項目需求分析2. 什麼是擴充卡模式?3. 擴充卡模式的工作原理4. 類擴充卡5. 對象擴充卡6. 接口擴充卡模式7. 擴充卡在SpringMVC架構應用的源碼分析8. 手寫SpringMvc通過擴充卡設計模式擷取對應Controller的源碼。9. 擴充卡模式的注意事項和細節

4.2 用類圖來描述

23種設計模式之擴充卡模式1. 項目需求分析2. 什麼是擴充卡模式?3. 擴充卡模式的工作原理4. 類擴充卡5. 對象擴充卡6. 接口擴充卡模式7. 擴充卡在SpringMVC架構應用的源碼分析8. 手寫SpringMvc通過擴充卡設計模式擷取對應Controller的源碼。9. 擴充卡模式的注意事項和細節

4.3 上代碼

4.3.1 被擴充卡類

/**
 * @author LongXi
 * @create 2021-08-11 21:11
 */
//被擴充卡類
public class Voltage220V {
    public int output220V(){
        int src = 220;
        System.out.println("電壓="+ src + "伏");
        return src;
    }
}

           

4.3.2 适配接口

/**
 * @author LongXi
 * @create 2021-08-11 21:13
 */
//适配接口
public interface IVoltage5V {
    public int output5V();
}
           

4.3.3 擴充卡類

/**
 * @author LongXi
 * @create 2021-08-11 21:14
 */
//擴充卡類
public class VoltageAdapter extends Voltage220V implements IVoltage5V {
    @Override
    public int output5V() {
        //擷取220V電壓
        int srcV = output220V();
        //轉成5V
        int dstV = srcV / 44;
        return dstV;
    }
}

           

4.3.4 手機類,使用擴充卡

/**
 * @author LongXi
 * @create 2021-08-11 21:17
 */
public class Phone {
    //充電
    public void charging(IVoltage5V iVoltage5V){
        if (iVoltage5V.output5V() == 5){
            System.out.println("電壓為5V,可以充電~~");
        } else if (iVoltage5V.output5V() > 5){
            System.out.println("電壓大于5V,不能充電~~");
        }
    }
}
           

4.3.5 測試類

/**
 * @author LongXi
 * @create 2021-08-11 21:21
 */
public class Client {
    public static void main(String[] args) {
        System.out.println("類擴充卡模式");
        Phone phone = new Phone();
        phone.charging(new VoltageAdapter());
    }
}

           

4.3.6 運作結果

電壓=220伏
電壓為5V,可以充電~~
           

4.4 類擴充卡模式注意事項和細節

4.4.1 缺點

  1. Java是單繼承機制,是以類擴充卡需要繼承src類,至一點算是一個缺點,因為這要求dst必須是接口,有一定局限性。
  2. src類方法在Adapter中都會暴露出來,也增加了使用的成本(output220V)。

4.4.2 優點

由于其繼承了src類,是以它可以根據需求重寫src類的方法,是的Adapter的靈活性增強了。

5. 對象擴充卡

5.1 對象擴充卡模式介紹

  1. 基本思路和類擴充卡模式相同,隻是将Adapter類作為修改,不是繼承src類,而是持有src類執行個體,以解決相容性的問題。即:持有src類,實作dst類接口,完成src->dst的适配。
  2. 根據“合成服用原則”,在系統中盡量使用關聯關系來替代繼承關系。
  3. 對象擴充卡模式是擴充卡模式常用的一種。
  4. 改進思路:隻需改進擴充卡即可。

5.2 用類圖來描述

23種設計模式之擴充卡模式1. 項目需求分析2. 什麼是擴充卡模式?3. 擴充卡模式的工作原理4. 類擴充卡5. 對象擴充卡6. 接口擴充卡模式7. 擴充卡在SpringMVC架構應用的源碼分析8. 手寫SpringMvc通過擴充卡設計模式擷取對應Controller的源碼。9. 擴充卡模式的注意事項和細節

5.3 上代碼

5.3.1 改進擴充卡類

**
 * @author LongXi
 * @create 2021-08-11 21:14
 */
//擴充卡類
public class VoltageAdapter implements IVoltage5V {
    //關聯關系中的聚合關系
    private Voltage220V voltage220V;

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

    @Override
    public int output5V() {
        int dst = 0;
        if (null != voltage220V){
            //擷取220V電壓
            int src = voltage220V.output220V();
            System.out.println("使用對象擴充卡,進行适配~");
            dst = src/44;
            System.out.println("适配完成,輸出電壓為:" + dst);
        }
        return dst;
    }
}

           

5.3.2 修改測試類,其他類不變

/**
 * @author LongXi
 * @create 2021-08-11 21:21
 */
public class Client {
    public static void main(String[] args) {
        System.out.println("對象擴充卡模式");
        Phone phone = new Phone();
        phone.charging(new VoltageAdapter(new Voltage220V()));
    }
}

           

5.3.3 運作結果

對象擴充卡模式
電壓=220伏
使用對象擴充卡,進行适配~
适配完成,輸出電壓為:5
電壓為5V,可以充電~~
           

5.4 對象擴充卡模式注意事項和細節

  1. 對象擴充卡和類擴充卡其實算是同一種思想,隻不過實作方式不同。根據合成複用原則,使用組合替代繼承,是以它解決了類擴充卡必須繼承src的局限性問題,也不再要求dst必須是接口。
  2. 使用成本更低,更靈活。

6. 接口擴充卡模式

6.1 接口擴充卡模式介紹

  1. 一些書籍稱為:擴充卡模式(Default Adapter Pattern)或預設擴充卡模式。
  2. 當不需要全部實作接口提供的方法時,可先設計一個抽象類實作接口,并為該接口中每個方法提供一個預設實作(空方法),那麼該抽象類的子類可有選擇的覆寫父類的某些方法來實作需求。
  3. 适用于一個接口不想使用其所有的方法的情況。

6.2 用類圖來描述

23種設計模式之擴充卡模式1. 項目需求分析2. 什麼是擴充卡模式?3. 擴充卡模式的工作原理4. 類擴充卡5. 對象擴充卡6. 接口擴充卡模式7. 擴充卡在SpringMVC架構應用的源碼分析8. 手寫SpringMvc通過擴充卡設計模式擷取對應Controller的源碼。9. 擴充卡模式的注意事項和細節

6.3 上代碼

6.3.1 接口

/**
 * @author LongXi
 * @create 2021-08-11 22:10
 */
public interface InterFace4 {
    public void m1();
    public void m2();
    public void m3();
    public void m4();
}
           

6.3.2 抽象擴充卡,實作所有方法

/**
 * @author LongXi
 * @create 2021-08-11 22:11
 */
//在AbsAdapter類中,我們将InterFace4的方法進行預設實作
public abstract class AbsAdapter implements InterFace4{
    @Override
    public void m1() {
    }
    @Override
    public void m2() {
    }

    @Override
    public void m3() {
    }
    @Override
    public void m4() {
    }
}

           

6.3.3 測試類

/**
 * @author LongXi
 * @create 2021-08-11 22:13
 */
public class Client {
    public static void main(String[] args) {
        AbsAdapter absAdapter = new AbsAdapter() {
            //隻需要去覆寫我們需要使用的接口方法
            @Override
            public void m1() {
                System.out.println("覆寫了m1方法");
            }
        };
        absAdapter.m1();
    }
}

           

6.3.4 運作結果

覆寫了m1方法
           

7. 擴充卡在SpringMVC架構應用的源碼分析

7.1 SpringMvc的HandlerAdapter,就使用了擴充卡模式。

7.1.1 DispatcherServlet類

23種設計模式之擴充卡模式1. 項目需求分析2. 什麼是擴充卡模式?3. 擴充卡模式的工作原理4. 類擴充卡5. 對象擴充卡6. 接口擴充卡模式7. 擴充卡在SpringMVC架構應用的源碼分析8. 手寫SpringMvc通過擴充卡設計模式擷取對應Controller的源碼。9. 擴充卡模式的注意事項和細節

8. 手寫SpringMvc通過擴充卡設計模式擷取對應Controller的源碼。

  1. Spring定義了一個擴充卡接口,是的每一種Contrller有一種對應的擴充卡實作類
  2. 擴充卡代替controller執行相應的方法。
  3. 擴充Controller時,隻需要增加一個擴充卡類就完成了SpringMvc的擴充了。
  4. 就是設計模式的力量。

8.1 用類圖來描述

23種設計模式之擴充卡模式1. 項目需求分析2. 什麼是擴充卡模式?3. 擴充卡模式的工作原理4. 類擴充卡5. 對象擴充卡6. 接口擴充卡模式7. 擴充卡在SpringMVC架構應用的源碼分析8. 手寫SpringMvc通過擴充卡設計模式擷取對應Controller的源碼。9. 擴充卡模式的注意事項和細節

8.2 上代碼

8.2.1 controller類

/**
 * @author LongXi
 * @create 2021-08-12 20:49
 */
public interface Controller {

}
class HttpController implements Controller{
    public void doHttpHandler(){
        System.out.println("http...");
    }
}
class SimpleController implements Controller{
    public void doSimpleHandler(){
        System.out.println("Simple...");
    }
}
class AnnotationController implements Controller{
    public void doAnnotationHandler(){
        System.out.println("Annotation...");
    }
}
           

8.2.2 擴充卡類

/**
 * @author LongXi
 * @create 2021-08-12 20:53
 */
//定義了Adapter接口
public interface HandlerAdapter {
    public boolean supports(Object handler);
    public void handler(Object handler);
}
//多種擴充卡
class SimpleHandlerAdapter implements HandlerAdapter{

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

    @Override
    public void handler(Object handler) {
        ((SimpleController)handler).doSimpleHandler();
    }
}
class HttpHandlerAdapter implements HandlerAdapter{

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

    @Override
    public void handler(Object handler) {
        ((HttpController)handler).doHttpHandler();
    }
}
class AnnotationHandlerAdapter implements HandlerAdapter{

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

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

8.2.3 DispatchServlet類

/**
 * @author LongXi
 * @create 2021-08-12 21:00
 */
public class DispatchServlet {
    public List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();
    public DispatchServlet() {
        handlerAdapters.add(new HttpHandlerAdapter());
        handlerAdapters.add(new SimpleHandlerAdapter());
        handlerAdapters.add(new AnnotationHandlerAdapter());
    }
    public void doDispatch(){
       //此處模拟SpringMvc從request取handler的對象。
       //擴充卡可以擷取到希望的Controller
        HttpController httpController = new HttpController();
//        SimpleController simpleController = new SimpleController();
//        AnnotationController annotationController = new AnnotationController();


        //得到對應擴充卡
       HandlerAdapter adapter =getHandler(httpController);
       // 通過擴充卡執行對應的controller所對應的方法
        adapter.handler(httpController);
    }
    public HandlerAdapter getHandler(Controller controller){
        for (HandlerAdapter adapter:this.handlerAdapters){
            if (adapter.supports(controller)){
                return adapter;
            }
        }
        return null;
    }

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

           

8.2.4 運作結果

9. 擴充卡模式的注意事項和細節

  1. 三種命名方式:是根據src是以怎麼樣的形式給到Adapter(在Adapter裡的形式)來命名的。
  2. 類擴充卡:以類給到,在Adapter裡,就是将src當作類,繼承。

    對象擴充卡:以對象給到,在Adapter裡,将src作為一個對象,持有。

    接口擴充卡:以接口給到,在Adapter裡,将src作為一個接口,實作。

  3. Adapter模式最大的作用還是将原本不相容的接口融合在一起工作。
  4. 實際開發中,實作起來不拘泥我們講解的三種經典形式。