設計模式之——攔截器模式

攔截器模式應用非常廣泛,適用場景一般在框架代碼中的固定業務邏輯,這部分邏輯通常不會變化,比如:服務調用的攔截處理,攔截服務的參數,參數國際化處理,攔截服務的異常,記錄服務的調用結果等等。

之所以要講這個,是因爲後面講SpringAOP的時候會參考到!

攔截器模式有三個重要的元素:調度器,攔截器,業務邏輯,只要充分理解這三個元素,攔截器模式就很簡單了。

  • 調度器

一個業務邏輯可以有N個攔截器,這些攔截器是怎麼運行的,自然是需要有一個調度器從中調度。

  • 攔截器

攔截器就只是負責攔截業務代碼,在業務代碼前後做一些操作,至於攔截器和業務代碼的關係,攔截器不會直接調用業務代碼,因爲會耦合,攔截器在處理完自己的邏輯,會通知調度器,由調度器負責後續的操作,是繼續攔截,還是調用業務邏輯。

  • 業務邏輯

業務代碼這一塊沒啥好說的。

 

舉個代碼最少的例子,業務場景:服務調用,攔截服務調用記錄日誌,以及做異常處理。

既然有兩個攔截器,自然要有一個攔截器接口。

1、攔截器接口

public interface Interceptor {
    void before(Invocation invocation);

    String intercept(Invocation invocation);

    void after(Invocation invocation);
}

2、日誌攔截器

public class LogInterceptor implements Interceptor {

    @Override
    public void before(Invocation invocation) {
        System.out.println("LogInterceptor before...");
    }

    @Override
    public String intercept(Invocation invocation) {
        this.before(invocation);
        invocation.invoke();
        this.after(invocation);
        return null;
    }

    @Override
    public void after(Invocation invocation) {
        System.out.println("LogInterceptor after...");
    }
}

3,異常攔截器

public class ExceptionInterceptor implements Interceptor {

    @Override
    public void before(Invocation invocation) {
        System.out.println("ExceptionInterceptor before...");
    }

    @Override
    public String intercept(Invocation invocation) {
        this.before(invocation);
        // 實際代碼應該是try catch,在catch中做事情
        invocation.invoke();
        this.after(invocation);
        return null;
    }

    @Override
    public void after(Invocation invocation) {
        System.out.println("ExceptionInterceptor after...");
    }
}

4、調度器代碼

public class Invocation {
    int index = 0;
    // 調度器管理業務
    private BusinessService bs;
    // 調度器管理攔截器List
    private List<Interceptor> interceptions = new ArrayList<Interceptor>();
    
    public Invocation() {
        interceptions.add(new LogInterceptor());
        interceptions.add(new ExceptionInterceptor());
    }
    
    public void invoke() {
        if (index == interceptions.size()) {
            bs.perform();
        }
        else {
            Interceptor interceptor = interceptions.get(index);
            index++;
            interceptor.intercept(this); // 傳this(調度器)用於回調
        }
    }
    
    public void setBusinessService(BusinessService bs) {
        this.bs = bs;
    }
}

5、業務代碼

public class BusinessService {

    public void perform() {
        System.out.println("服務調用。。。");
    }
}

6,測試方法

    public static void main(String[] args) {
        Invocation invocation = new Invocation(); // 直接在構造裏面就把兩個攔截器加上
        invocation.setBusinessService(new BusinessService()); // 加上業務邏輯

        invocation.invoke();
    }

輸出結果:

LogInterceptor before...
ExceptionInterceptor before...
服務調用。。。
ExceptionInterceptor after...
LogInterceptor after...

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章