1. Application Scenario:
1) We want to build an BBS and enable user to post their comments.
How can we filter the sensitive messages that user posted?
2) In chatting room, our message are filtered and tagged as " Davy Says: *** "
" Davy Says " has been added into message.
2. Traditional Approach:
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public class MsgProcessor { private String msg; public String process() { // process html <> tag String result = msg.replaceAll("<", "{").replaceAll(">", "}"); // process sensitive words result = result.replaceAll("Sensitive", "Non-sensitive").replaceAll( "Bad", "Good"); return result; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; import org.junit.Test; public class AppTest { private String message = "Sensitive, <script>, Hello World, Forbidden, Bad"; @Test public void test() { MsgProcessor processor = new MsgProcessor(); processor.setMsg(message); String result = processor.process(); System.out.println(result); } }
Non-sensitive, {script}, Hello World, Forbidden, Good
Comments:
1) As we can see, the processor is tightly coupled with the message itself and the rules.
2) Every time we want to add some new rules, we have to change the code inside the method process().
3) How can we use another more flexible and low-coupled approach to realize this?
--> We can make several filters, each filter focus on its specific rules.
--> Every time we want to add or delete some rules, we just add or delete the fiters.
3. Chain Of Responsibility Approach
1) Filter Interface
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public interface Filter { String doFiler(String msg); }
2) HtmlFilter
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public class HtmlFilter implements Filter { public String doFiler(String msg) { return msg.replaceAll("<", "{").replaceAll(">", "}"); } }
3) SensitiveFilter
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public class SensitiveFilter implements Filter { public String doFiler(String msg) { return msg.replaceAll("Sensitive", "Non-sensitive").replaceAll("Bad", "Good"); } }
4) MsgProcessor
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public class MsgProcessor { private String msg; private List<Filter> filterList; public MsgProcessor() { filterList = new ArrayList<Filter>(); filterList.add(new HtmlFilter()); filterList.add(new SensitiveFilter()); } public MsgProcessor() { } public String process() { for (Filter filter : filterList) { msg = filter.doFiler(msg); } return msg; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
5) Test Case
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; import org.junit.Test; public class AppTest { private String message = "Sensitive, <script>, Hello World, Forbidden, Bad"; @Test public void test() { MsgProcessor processor = new MsgProcessor(); processor.setMsg(message); String result = processor.process(); System.out.println(result); } }
6) Output
Non-sensitive, {script}, Hello World, Forbidden, Good
Comments:
1) Using List we can set the sequence of filter that take effect. That is easy to organize which filter execute first and which filter execute last.
2) Still there are further requirements:
1) If there is a filter-chain that already exists. And we want want to add this chain's function into our own filter-chain. How can we easily achieve this?
2) How can we easily conbine several chains together?
--> We can get all the filters that in previous filter-chain, and add these filers into our own filter-chain. But that is not convenience enough.
--> As we can see, a filter-chain performs the same function as a filter.
1) Added a new class named FilterChain
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; import java.util.ArrayList; import java.util.List; public class FilterChain implements Filter { private List<Filter> filterList = new ArrayList<Filter>(); public String doFiler(String msg) { for (Filter filter : filterList) { msg = filter.doFiler(msg); } return msg; } public FilterChain addFilter(Filter filter) { filterList.add(filter); return this; } public void removeFilter(Filter filter) { filterList.remove(filter); } }
2) Test case as below
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; import org.junit.Test; public class AppTest { private String message = "Sensitive, <script>, Hello World, Forbidden, Bad"; @Test public void test() { FilterChain filterChain = new FilterChain(); filterChain.addFilter(new HtmlFilter()) .addFilter(new SensitiveFilter()); message = filterChain.doFiler(message); System.out.println(message); } }
3) Output is still correct.
4. Still there are futher requirements:
1) We want bi-directional filter which can not only filter the request but also filter the response.
2) And the request/response message may not be simple String type.
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public class Request { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public class Response { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public interface Filter { void doFiler(Request request, Response response); }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public class HtmlFilter implements Filter { public void doFiler(Request request, Response response) { request.setMessage(request.getMessage().replaceAll("<", "{") .replaceAll(">", "}")); } }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public class SensitiveFilter implements Filter { public void doFiler(Request request, Response response) { request.setMessage(request.getMessage() .replaceAll("Sensitive", "Non-sensitive") .replaceAll("Bad", "Good")); } }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; import java.util.ArrayList; import java.util.List; public class FilterChain implements Filter { private List<Filter> filterList = new ArrayList<Filter>(); public void doFiler(Request request, Response response) { for (Filter filter : filterList) { filter.doFiler(request, response); } } public FilterChain addFilter(Filter filter) { filterList.add(filter); return this; } public void removeFilter(Filter filter) { filterList.remove(filter); } }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; import org.junit.Test; public class AppTest { private String requestMsg = "Sensitive, <script>, Hello World, Forbidden, Bad"; private String responseMsg = "Sensitive, <script>, Hello World, Forbidden, Bad"; @Test public void test() { FilterChain filterChain = new FilterChain(); filterChain.addFilter(new HtmlFilter()) .addFilter(new SensitiveFilter()); Request request = new Request(); request.setMessage(requestMsg); Response response = new Response(); response.setMessage(responseMsg); filterChain.doFiler(request, response); System.out.println(request.getMessage()); System.out.println(response.getMessage()); } }
Non-sensitive, {script}, Hello World, Forbidden, Good Sensitive, <script>, Hello World, Forbidden, Bad
Comments:
1) We only move one step futher which encapsulate the type of request and response.
2) We only process the request and still didn't make any procession to our response object.
3) Below is the final solution for this problem.
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public interface Filter { void doFiler(Request request, Response response, FilterChain filterChain); }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public class HtmlFilter implements Filter { public void doFiler(Request request, Response response, FilterChain filterChain) { request.setMessage(request.getMessage().replaceAll("<", "{") .replaceAll(">", "}").concat("---Processed by HtmlFilter")); filterChain.doFiler(request, response, filterChain); response.setMessage(response.getMessage().replaceAll("<", "{") .replaceAll(">", "}").concat("---Processed by HtmlFilter")); } }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; public class SensitiveFilter implements Filter { public void doFiler(Request request, Response response, FilterChain filterChain) { request.setMessage(request.getMessage() .replaceAll("Sensitive", "Non-sensitive") .replaceAll("Bad", "Good") .concat("---Processed by SensitiveFilter")); filterChain.doFiler(request, response, filterChain); response.setMessage(response.getMessage() .replaceAll("Sensitive", "Non-sensitive") .replaceAll("Bad", "Good") .concat("---Processed by SensitiveFilter")); } }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; import java.util.ArrayList; import java.util.List; public class FilterChain implements Filter { private List<Filter> filterList = new ArrayList<Filter>(); private int index = 0; public void doFiler(Request request, Response response, FilterChain filterChain) { if (index == filterList.size()) { return; } else { Filter filter = filterList.get(index); index++; filter.doFiler(request, response, filterChain); } } public FilterChain addFilter(Filter filter) { filterList.add(filter); return this; } public void removeFilter(Filter filter) { filterList.remove(filter); } }
package edu.xmu.designPattern.DesignPattern_ChaniOfResponsibility; import org.junit.Test; public class AppTest { private String requestMsg = "Request: Sensitive, <script>, Hello World, Forbidden, Bad"; private String responseMsg = "Response: Sensitive, <script>, Hello World, Forbidden, Bad"; @Test public void test() { FilterChain filterChain = new FilterChain(); filterChain.addFilter(new HtmlFilter()) .addFilter(new SensitiveFilter()); Request request = new Request(); request.setMessage(requestMsg); Response response = new Response(); response.setMessage(responseMsg); filterChain.doFiler(request, response, filterChain); System.out.println(request.getMessage()); System.out.println(response.getMessage()); } }
Request: Non-sensitive, {script}, Hello World, Forbidden, Good---Processed by HtmlFilter---Processed by SensitiveFilter Response: Non-sensitive, {script}, Hello World, Forbidden, Good---Processed by SensitiveFilter---Processed by HtmlFilter
Extension:
1) We can take a look at Servlet API. And we can find out interfaces
-> javax.servlet.FilterChain interface
-> javax.servlet.Filter interface
There is a limitation that wa cannot add a filterchain to another as Filter and FilterChain are two different interfaces.
This design is akward and can be improved as above.
相关推荐
该项目是作为帖子的材料开发的: : 运行这个项目 进行此操作的节点的版本: v12.18.0 (此信息可能有用..我不知道.. :thinking_face: ) 安装依赖项: npm install 编译打字稿并运行编译后的 ...
★附录A介绍了剩下的设计模式:Bridge(桥接)、Builder(生成器)、Chainof Responsibility(责任链)、Flyweight(蝇量)、Interpreter(解释器)、Mediator(中介者)、Memento(备忘录)、Prototype(原型)、...
8. **责任链模式 (Chain of Responsibility Pattern)**:22-chain-of-responsibility中,你可以看到如何创建一个处理请求的对象链,每个对象都可以处理请求或传递给下一个对象。这有助于避免硬编码的条件分支,提高...
- 责任链模式(Chain of Responsibility):避免将处理请求的对象耦合到发送者。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求或者参数化不同请求。 - 解释器模式(Interpreter)...
- 责任链模式(Chain of Responsibility):避免对象之间的耦合,将请求沿着处理者链传递,直到某个对象处理它。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求或记录请求日志。 -...
3. 行为型模式:这类模式定义了对象之间的通信和责任分配,包括策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、迭代器模式(Iterator)、责任链模式(Chain of Responsibility)...
- 责任链模式(Chain of Responsibility):将请求沿着处理者链传递,直到某个处理者处理它。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求、支持撤销操作。 - 解释器模式...
- 责任链模式(Chain of Responsibility):避免将请求的发送者和接收者耦合在一起,让多个对象都有可能处理请求。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求或支持可撤销的...
十一个行为型模式 十一个行为型模式 职责链模式-Chain of Responsibility Pattern 请求的链式处理——职责链模式(一) 请求的链式处理——职责链模式(二) 请求的链式处理——职责链模式(三) 请求的链式处理——...
- 责任链模式(Chain of Responsibility):避免将请求的发送者和接收者耦合在一起,将多个处理者对象链接在一起形成链。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求、支持撤销...
Chain of Responsibility(职责链模式)** - **定义**:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 - **应用场景**:适用于处理多个请求处理者的场景,每个处理者要么处理请求,...
- **责任链模式(Chain of Responsibility)**:避免将处理逻辑硬编码,而是将请求沿着处理者链传递,直到某个处理者处理它。 - **命令模式(Command)**:将请求封装为一个对象,以便使用不同的请求、队列请求或...
CoreJava-DesignPattern 创意设计模式 -- Abstract Factory - Done ... -- Chain of Responsibility -- Command -- Interpreter -- Iterator -- Mediator -- Memento -- Null Object -- Observer -- State --
- **责任链模式(Chain of Responsibility)**:将请求沿着处理者链进行传递,直到有处理者处理为止。 - **命令模式(Command)**:将请求封装为一个对象,以便使用不同的请求、队列请求或参数化不同请求。 - **...
- **职责链模式(Chain of Responsibility)**:将请求沿着处理者链进行传递,直到有处理者处理该请求为止。 - **命令模式(Command)**:将请求封装为一个对象,以便使用不同的请求、队列或者日志请求,以及支持...
- 责任链模式(Chain of Responsibility):避免将请求的发送者和接收者耦合在一起,让多个对象都有可能处理这个请求。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求,或者支持可...
13. 责任链(Chain of Responsibility): - 目的:将请求沿着处理者链传递,直到某个处理者处理它。 - 应用场景:避免硬编码的多级条件分支,简化请求处理逻辑。 14. 命令(Command): - 目的:将请求封装为一...
行为型模式涉及到对象间如何交互,如策略(Strategy)、观察者(Observer)和责任链(Chain of Responsibility)。 .NET Framework 4.5 是微软的一个强大的开发平台,支持多种编程语言,并提供了大量的类库和服务,...
如命令(Command)、解释器(Interpreter)、迭代器(Iterator)、中介者(Mediator)、备忘录(Memento)、观察者(Observer)、状态(State... Method)、访问者(Visitor)和责任链(Chain of Responsibility)...