1. 程式人生 > 實用技巧 >設計模式(五)之介面卡模式

設計模式(五)之介面卡模式

時空連結:

  1. 設計模式(一)之策略模式
  2. 設計模式(二)之責任鏈模式
  3. 設計模式(三)之模板模式
  4. 設計模式(四)之裝飾者模式
  5. 設計模式(五)之介面卡模式

介面卡模式

概念

  1. 介面卡模式(Adapter Pattern)是作為兩個不相容的介面之間的橋樑。這種型別的設計模式屬於結構模式,它結合了兩個獨立介面的功能。
  2. 這種模式涉及到一個單一的類,該類負責加入獨立的或者不相容的介面功能。
  3. 它將一個系統的介面轉換成另外一種形式,從而使原來不能直接呼叫的介面變的可以呼叫。

特點

  • 源(Adaptee):需要被適配的物件或型別,舊版本或者是記憶體卡和筆記本之間的讀卡器。
  • 介面卡(Adapter):連線目標和源的中間物件,相當於一個轉換器,新舊版本可以實現相容。
  • 目標(Target):客戶所期待的介面。目標可以使具體的或抽象的類,也可以是介面。

使用場景

新老版本介面的相容。

優缺點

  • 優點

    1. 可以讓任何兩個沒有關聯的類一起遠行。
    2. 提高了類的複用。
    3. 增加了類的透明度。
    4. 靈活性好。
  • 缺點

    1. 過多的使用介面卡,會讓系統非常零亂,不易整體把握。

模式的結構

SpringMvc是一個非常棒的框架,配置相對靈活,實現簡單。今天我們就模擬一個有關介面卡的適配過程和簡單使用。

開發步驟

  • 模擬SpringMvc的DispatcherServlet物件,對請求進行派發。我們也編寫一個和它一樣的doService方法,如下圖:


      在該方法內部,呼叫 doDispatch方法




      從所有的介面卡物件當中挑選出唯一一個對應此請求handler的介面卡




      getHandlerAdapter方法內部,呼叫介面卡中的supports方法,判斷是否支援請求handler




      大致有哪些HandlerAdapter呢?





      我們上面有見到有一個supports方法,介面卡的方法是定義在一個統一的父類當中的,主要包含兩個方法,supports判斷是否支援對應的handler請求,

handle則是處理具體的handler請求,那讓我們來看看,如下圖:





      到這裡也看到其實並不難實現。下面我們就開始吧。


      定義一個類似於DispatcherServlet的處理類

package com.lee.adapter.controller;

import com.lee.adapter.service.HandlerAdapter;
import com.lee.adapter.service.impl.RequestMappingHandlerAdapter;
import com.lee.adapter.service.impl.SimpleHandlerAdapter;
import com.lee.adapter.service.impl.SimpleServletHandlerAdapter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zfl_a
 * @Desc 入口測試
 * @date 2020/8/16
 * @project springboot_design_pattern
 */
@RestController
public class DispatcherController implements InitializingBean {

    //自動裝配
    @Autowired
    private Map<String,Controller> controllerMap = new HashMap<>();

    private List<HandlerAdapter> handlerAdapters = new ArrayList<>();

    /**
     * 處理
     * @param controllerName simpleController simpleServletController httpRequestController
     * @return
     */
    @GetMapping("/doService")
    public String doService(String controllerName){

        return doDispatcher(controllerName);
    }

    private String doDispatcher(String controllerName) {

        // 獲取介面卡 引數可根據具體的Handler替換
        Controller controller = controllerMap.get(controllerName);
        HandlerAdapter ha = getHandlerAdapter(controller);
        if(ha == null) {
            return "沒有此介面卡";
        }
        //具體處理
        return ha.handle(controller);
    }

    /**
     * 獲取介面卡
     * @param controller
     * @return
     */
    private HandlerAdapter getHandlerAdapter(Controller controller) {
        if (this.handlerAdapters != null) {
            for (HandlerAdapter ha : this.handlerAdapters) {
                if (ha.supports(controller)) {
                    return ha;
                }
            }
        }
        return null ;
    }

    @Override
    public void afterPropertiesSet() throws Exception {

        //初始化介面卡例項
        RequestMappingHandlerAdapter mappingHandlerAdapter = new RequestMappingHandlerAdapter();
        SimpleHandlerAdapter simpleHandlerAdapter = new SimpleHandlerAdapter();
        SimpleServletHandlerAdapter servletHandlerAdapter = new SimpleServletHandlerAdapter();
        handlerAdapters.add(mappingHandlerAdapter);
        handlerAdapters.add(simpleHandlerAdapter);
        handlerAdapters.add(servletHandlerAdapter);
    }
}

  • 模擬Controller請求類

      定義一個共同的Controller,什麼也不做

package com.lee.adapter.controller;

/**
 * @author zfl_a
 * @date 2020/8/16
 * @project springboot_design_pattern
 */
public interface Controller {
}

      定義對應的實現類,做具體處理的

package com.lee.adapter.controller;

import org.springframework.stereotype.Component;

/**
 * @author zfl_a
 * @date 2020/8/16
 * @project springboot_design_pattern
 */
@Component
public class HttpRequestController implements Controller {

    public String doRequestMapping(){
        return "do http request ....";
    }

}

package com.lee.adapter.controller;

import org.springframework.stereotype.Component;

/**
 * @author zfl_a
 * @date 2020/8/16
 * @project springboot_design_pattern
 */
@Component
public class SimpleController implements Controller {

    public String doSimple(){
        return "do simple ....";
    }
}

package com.lee.adapter.controller;

import org.springframework.stereotype.Component;

/**
 * @author zfl_a
 * @date 2020/8/16
 * @project springboot_design_pattern
 */
@Component
public class SimpleServletController implements Controller {

    public String doSimpleServlet(){
        return "do Simple Servlet....";
    }
}

  • 定義一個和HandlerAdapter的介面卡介面
package com.lee.adapter.service;

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author zfl_a
 * @Desc 所有介面卡的父類
 * @date 2020/8/16
 * @project springboot_design_pattern
 */
public interface HandlerAdapter {

    boolean supports(Object handler);

    String handle(Object handler) ;

}

  • 定義和上面Controller對應的Adapter
package com.lee.adapter.service.impl;

import com.lee.adapter.controller.HttpRequestController;
import com.lee.adapter.service.HandlerAdapter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author zfl_a
 * @date 2020/8/16
 * @project springboot_design_pattern
 */
public class RequestMappingHandlerAdapter implements HandlerAdapter {

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

    @Override
    public String handle(Object handler)  {

        return ((HttpRequestController)handler).doRequestMapping();
    }
}

package com.lee.adapter.service.impl;

import com.lee.adapter.controller.SimpleController;
import com.lee.adapter.service.HandlerAdapter;
import org.springframework.stereotype.Component;

/**
 * @author zfl_a
 * @date 2020/8/16
 * @project springboot_design_pattern
 */
public class SimpleHandlerAdapter implements HandlerAdapter {

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

    @Override
    public String handle(Object handler)  {
        return ((SimpleController)handler).doSimple();
    }
}

package com.lee.adapter.service.impl;

import com.lee.adapter.controller.SimpleServletController;
import com.lee.adapter.service.HandlerAdapter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author zfl_a
 * @date 2020/8/16
 * @project springboot_design_pattern
 */
public class SimpleServletHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return handler instanceof SimpleServletController;
    }

    @Override
    public String handle(Object handler) {

        return ((SimpleServletController)handler).doSimpleServlet();
    }
}

測試結果如下:

  • 當請求引數為 ?controllerName=simpleServletController時:

  • 當請求引數為 ?controllerName=httpRequestController時: