抽絲剝繭設計模式- 責任鏈模式(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()替換字串的效果是一樣,即這兩者也支援字串的操作;
感謝閱讀到現在,請在留言區提出寶貴的意見!
更多精彩內容,關注微信公眾號:技術嚴選