1. 程式人生 > 其它 >抽絲剝繭設計模式- 責任鏈模式(Chain of Responsibility Pattern)

抽絲剝繭設計模式- 責任鏈模式(Chain of Responsibility Pattern)

一、關於設計模式的思考
  1.很多設計模式的區別不是語法的區別,而是語義的區別。
  2.最難的是proxy,其次是chain of responsibility,Reactor 也當作設計模式。
  3.所謂設計模式 就是把簡單問題複雜化,把變化的部分封裝那,即"封裝變化"。
  4.大部分的設計模式都是利用Java多型,多型是Java面向物件的核心。

二、請思考如下需求:
  在公眾號上發表文章,後臺要經過處理才能發表和存如資料庫,每個處理策略都要檢查一遍。

三、責任鏈模式(Chain of Responsibility Pattern)
  讓多個處理請求的物件都有可能接收請求,將這些處理請求的物件連線成一條鏈,並且沿著這條鏈傳遞請求,直到有物件處理它為止。

四、例子

package org.design.behavioral.chain;

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

public class ChainOfResponsibility {
    public static void main(String[] args) {
        Article article = new Article();
        article.setArticle("Hello every one,(--)<script> This is a sensitive word! 666");
        //java是值傳遞,函式呼叫的時候如果是基本型別,傳值的copy,如果是引用型別,傳的是引用型別地址的copy

        //version 1 需要過濾文章中惡意指令碼和敏感詞
        /*
        String str = article.getArticle();
        //過濾惡意指令碼
        str = str.replace("<","[");
        str = str.replace(">","]");
        //過濾敏感詞
        str = str.replace("sensitive","*");
        article.setArticle(str);
        System.out.println(article);
         */

        //version 2 將過濾策略封裝到Filter類中
        /*
        Filter scriptFilter = new ScriptFilter();
        scriptFilter.doFilter(article);
        Filter sensitiveFilter = new SensitiveFilter();
        sensitiveFilter.doFilter(article);
        System.out.println(article);
        */

        //version 3  藉助list,形成鏈
        /*
        List<Filter> filters = new ArrayList<Filter>();
        filters.add(new ScriptFilter());
        filters.add(new SensitiveFilter());
        filters.add(new ExpressionFilter());
        filters.add(new NumberFilter());
        for(Filter f:filters){
            f.doFilter(article);
        }
        System.out.println(article);
        */

        //version 4 filter chain,與version相比,只不過把add 和遍歷方法放到FilterChainV1中了。
        //程式設計小技巧:將Filter們構成鏈條,鏈式程式設計。
        /*
        FilterChainV1 chainV1 = new FilterChainV1();
        chainV1.add(new ScriptFilter()).add(new NumberFilter());
        chainV1.doFilter(article);
        System.out.println(article);

        FilterChainV1 chainV2 = new FilterChainV1();
        chainV2.add(new ExpressionFilter()).add(new SensitiveFilter());
        chainV2.doFilter(article);
        System.out.println(article);
        */
        /*
        version 5 FilterChain其實自己也是一個Filter,像遞迴。
        FilterChainV2 implements Filter

        FilterChainV2 chainV21 = new FilterChainV2();
        chainV21.add(new ScriptFilter()).add(new NumberFilter());

        FilterChainV2 chainV22 = new FilterChainV2();
        chainV22.add(new ExpressionFilter()).add(new SensitiveFilter());

        chainV21.add(chainV22);
        chainV21.doFilter(article);
        System.out.println(article);
        */
        /*
        version 6 由FilterChain中的某一個Filter決定鏈條是否繼續。Filter中增加返回值,繼續返回true,終止返回false。
        判斷邏輯放在FilterChain中不合適,由Filter自己決定是否繼續更合理。
        因為擴充套件Filter的時候,應該由擴充套件的Filter決定是否繼續,不用修改FilterChain。
        */
        FilterChin chain = new FilterChin();
        chain.add(new ScriptFilter()).add(new NumberFilter()).add(new ExpressionFilter()).add(new SensitiveFilter());
        chain.doFilter(article);
        System.out.println(article);


    }
}

class Article {
    public String article;

    public String getArticle() {
        return article;
    }

    public void setArticle(String article) {
        this.article = article;
    }

    @Override
    public String toString() {
        return "Article{" +
                "article='" + article + '\'' +
                '}';
    }
}

interface Filter {
    boolean doFilter(Article article);
}

class ScriptFilter implements Filter {

    @Override
    public boolean doFilter(Article article) {
        System.out.println("Exec ScriptFilter");
        //過濾惡意指令碼
        String str = article.getArticle();
        str = str.replace("<", "[");
        str = str.replace(">", "]");
        article.setArticle(str);
        return true;
    }
}

class SensitiveFilter implements Filter {

    @Override
    public boolean doFilter(Article article) {
        System.out.println("Exec SensitiveFilter");
        //過濾敏感詞
        String str = article.getArticle();
        str = str.replace("sensitive", "*");
        article.setArticle(str);
        return false;
    }
}

class ExpressionFilter implements Filter {

    @Override
    public boolean doFilter(Article article) {
        System.out.println("Exec ExpressionFilter");
        //過濾表情
        String str = article.getArticle();
        str = str.replace("(--)", "@");
        article.setArticle(str);
        return true;
    }
}

class NumberFilter implements Filter {

    @Override
    public boolean doFilter(Article article) {
        System.out.println("Exec NumberFilter");
        //過濾數字
        String str = article.getArticle();
        str = str.replaceAll("\\d", "000");
        article.setArticle(str);
        return true;
    }
}

class FilterChainV1 {
    List<Filter> filters = new ArrayList<Filter>();

    ////程式設計小技巧:return FilterChain,將FilterChain形成鏈 類似StringBuffer.append();
    public FilterChainV1 add(Filter filter) {
        this.filters.add(filter);
        return this;
    }

    public void doFilter(Article article) {
        for (Filter f : filters) {
            f.doFilter(article);
        }
    }
}

class FilterChainV2 implements Filter {
    List<Filter> filters = new ArrayList<Filter>();

    ////程式設計小技巧:return FilterChain,將FilterChain形成鏈 類似StringBuffer.append();
    public FilterChainV2 add(Filter filter) {
        this.filters.add(filter);
        return this;
    }

    public boolean doFilter(Article article) {
        for (Filter f : filters) {
            f.doFilter(article);
        }
        return true;
    }
}

class FilterChin implements Filter {
    List<Filter> filters = new ArrayList<Filter>();

    FilterChin add(Filter filter) {
        this.filters.add(filter);
        return this;
    }

    @Override
    public boolean doFilter(Article article) {
        for (Filter f : filters) {
            if (!f.doFilter(article)) ;
            return false;
        }
        return true;
    }
}

 

五、補充知識:
  1.replace的引數是char和CharSequence,既可以支援字元的替換,也支援字串的替換(CharSequence字串序列);
  2.replaceAll的引數是regex或者char,基於正則表示式的替換,例如通過replaceAll("\\d", "#")把一個字串所有的數字字元都換成#號;
  3.相同點:均為全部替換,把源字串中的某一字元或字串全部換成指定的字元或字串。
  4.如果只想替換第一次出現的,使用replaceFirst(),改方法也是基於正則表示式的替換,與replaceAll()不同的時,僅替換第一次出現的字串;
  5.如果replaceAll()和replaceFirst()所用的引數據不是基於正則表示式,則與replace()替換字串的效果是一樣,即這兩者也支援字串的操作;

感謝閱讀到現在,請在留言區提出寶貴的意見!

更多精彩內容,關注微信公眾號:技術嚴選