再談裝飾器模式

前言

去年作大實驗初次接觸了裝飾器模式,當時也是懵懵懂懂過去了,沒有太搞明白。最近學習的時候又接觸了裝飾器模式,同時又有了一些新的理解。app

舉例

咱們會用到框架自帶的已經封裝好的方法,這節省了咱們寫不少原生方法的時間,可是這些封裝好的代碼可能又不是十分符合咱們所須要的,咱們須要對此進行一些修改。就如同它的名字,咱們須要對封裝好的代碼進行一下「裝飾」。
咱們本着對對修改關閉,對擴展開放的原則,對代碼進行修改。在這裏我舉個例子。
原來有一家生產並在本地零售玻璃杯的廠家,有一天來了一個商人說要訂購大量玻璃杯並運輸到外地去賣,他但願廠家能夠吧生產的玻璃杯用泡沫板包裝好以即可以運輸。這是廠家特地開闢了一條生產線去給杯子包裹泡沫板,這時商家滿意了。
商家想要買杯子,可是如今生產的杯子沒有徹底獲得他的滿意,因而廠家在不改變原來生產線的狀況下,添加了新的生產線,來知足客戶需求。客戶獲得的仍是杯子,可是是被裝飾過的杯子。這就是咱們的裝飾器模式。框架

doem

仍是那教程中例子來講明dom

class Request {
    String getHeader(String key) {
        // 獲取header值的真實代碼略
    }
}

class TokenFilterTest {
   
    /**在此傳入auth-token的值*/
    @Test
    void doFilter() {
        String authToken = "654321";
        Request request = new Request();
        this.getAuthUser(request);
    }
    /** 在此獲取auth-token的值 */
    void getAuthUser(Request request) {
        // 獲取auth-token
        request.getHeader("auth-token");
        // 根據auth-token獲取當前登陸用戶
    }

}

假設框架已經封裝好了Request類和類裏的getHeader方法,咱們在TokenFilterTest類裏須要調用getHeader方法,可是getHeader方法是框架爲咱們封裝好的,咱們不能改變他的代碼,可是現有的方法又打不到咱們如今的需求,咱們就爲他創建一個新的類,可是必定要繼承咱們原來的類。ide

class RequestWrapper extends Request {
    Request request; 
    
    private RequestWrapper() { 
    }
    
    public RequestWrapper(Request request) { 
        this.request = request;
    }

    @Override
    String getHeader(String key) { 
        return this.request.getHeader(key); 
    }
}

咱們經過繼承Request類是能夠調用getHeader方法的,可是咱們的目的是在這個方法的基礎上進行改造,函數

class RequestWrapper extends Request {
    ...
    @Override
    String getHeader(String key) {
        if ("auth-token".equals(key)) {
            // 在此返回新的auth-token值
            return "456789";
        }
        return this.request.getHeader(key);
    }
}

這樣一個新的方法就寫好了,咱們如今去調用這個方法學習

public class TokenFilterTest {

    @Test
    public void doFilter() {
        String authToken = new RandomString(6).nextString();
        System.out.println("authToken傳入值爲" + authToken);
        Request request = new Request();
        RequestWrapper requestWrapper = new RequestWrapper(request, authToken);
        this.getAuthUser(requestWrapper);
    }
    
    
    /** 在此獲取auth-token的值 */
    void getAuthUser(Request request) {
        // 獲取auth-token
        System.out.println("獲取到的auth-token值爲:" + request.getHeader("auth-token"));

        // 根據auth-token獲取當前登陸用戶
    }

}

咱們發現咱們在getAuthUser方法並無改變他傳入的參數類型,可是咱們在調用他的時候已經由傳入request變成requestWrapper,說明咱們並無改變他的類型,可是咱們確實是用的RequestWrapper構造函數獲取到的。
image.png
原來咱們三個方法的關係是這樣的.
image.png
如今咱們對他裝飾一下。咱們發現咱們並無改變getAuthUser。也不用改變getHeader,由於咱們的RequestWrapper類繼承了Request類。this

總結

對於裝飾器模式已經有不少次接觸了,每次接觸都會帶來新的理解,也會帶來提升。spa

相關文章
相關標籤/搜索