`
DavyJones2010
  • 浏览: 151890 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

DesignPattern : Chain-Of-Responsibility

阅读更多

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.

分享到:
评论

相关推荐

    design-pattern-chain-of-responsibility:created旨在研究责任链设计模式的项目:chains:

    该项目是作为帖子的材料开发的: : 运行这个项目 进行此操作的节点的版本: v12.18.0 (此信息可能有用..我不知道.. :thinking_face: ) 安装依赖项: npm install 编译打字稿并运行编译后的 ...

    Design Patterns by Tutorials in Swift 4.2, 2nd Edition_code

    8. **责任链模式 (Chain of Responsibility Pattern)**:22-chain-of-responsibility中,你可以看到如何创建一个处理请求的对象链,每个对象都可以处理请求或传递给下一个对象。这有助于避免硬编码的条件分支,提高...

    DesignPattern::pencil:设计模式_java实现以及详解

    - 责任链模式(Chain of Responsibility):避免将处理请求的对象耦合到发送者。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求或者参数化不同请求。 - 解释器模式(Interpreter)...

    Design Pattern英文版

    - 责任链模式(Chain of Responsibility):避免对象之间的耦合,将请求沿着处理者链传递,直到某个对象处理它。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求或记录请求日志。 -...

    设计模式java源码-design-pattern:java设计模式源代码

    3. 行为型模式:这类模式定义了对象之间的通信和责任分配,包括策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、迭代器模式(Iterator)、责任链模式(Chain of Responsibility)...

    DesignPattern:C#设计模式示例

    - 责任链模式(Chain of Responsibility):将请求沿着处理者链传递,直到某个处理者处理它。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求、支持撤销操作。 - 解释器模式...

    DesignPattern-master.zip

    - 责任链模式(Chain of Responsibility):避免将请求的发送者和接收者耦合在一起,让多个对象都有可能处理请求。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求或支持可撤销的...

    design-pattern-java.pdf

    十一个行为型模式 十一个行为型模式 职责链模式-Chain of Responsibility Pattern 请求的链式处理——职责链模式(一) 请求的链式处理——职责链模式(二) 请求的链式处理——职责链模式(三) 请求的链式处理——...

    design patterns elements of reusable object-oriented software

    ★附录A介绍了剩下的设计模式:Bridge(桥接)、Builder(生成器)、Chainof Responsibility(责任链)、Flyweight(蝇量)、Interpreter(解释器)、Mediator(中介者)、Memento(备忘录)、Prototype(原型)、...

    DesignPattern:设计模式

    - 责任链模式(Chain of Responsibility):避免将请求的发送者和接收者耦合在一起,将多个处理者对象链接在一起形成链。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求、支持撤销...

    Design Pattern 简明手册

    Chain of Responsibility(职责链模式)** - **定义**:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 - **应用场景**:适用于处理多个请求处理者的场景,每个处理者要么处理请求,...

    阅读java源码-JavaDesignPattern:23种设计模式Java实现

    - **责任链模式(Chain of Responsibility)**:避免将处理逻辑硬编码,而是将请求沿着处理者链传递,直到某个处理者处理它。 - **命令模式(Command)**:将请求封装为一个对象,以便使用不同的请求、队列请求或...

    CoreJava-DesignPattern

    CoreJava-DesignPattern 创意设计模式 -- Abstract Factory - Done ... -- Chain of Responsibility -- Command -- Interpreter -- Iterator -- Mediator -- Memento -- Null Object -- Observer -- State --

    DesignPattern:设计模式演示程序

    - **责任链模式(Chain of Responsibility)**:将请求沿着处理者链进行传递,直到有处理者处理为止。 - **命令模式(Command)**:将请求封装为一个对象,以便使用不同的请求、队列请求或参数化不同请求。 - **...

    designPattern:设计模式相关代码实现

    - **职责链模式(Chain of Responsibility)**:将请求沿着处理者链进行传递,直到有处理者处理该请求为止。 - **命令模式(Command)**:将请求封装为一个对象,以便使用不同的请求、队列或者日志请求,以及支持...

    design-pattern-in-java

    - 责任链模式(Chain of Responsibility):避免将请求的发送者和接收者耦合在一起,让多个对象都有可能处理这个请求。 - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求,或者支持可...

    summary of design patterns

    13. 责任链(Chain of Responsibility): - 目的:将请求沿着处理者链传递,直到某个处理者处理它。 - 应用场景:避免硬编码的多级条件分支,简化请求处理逻辑。 14. 命令(Command): - 目的:将请求封装为一...

    Design*Pattern*Framework*4.5

    行为型模式涉及到对象间如何交互,如策略(Strategy)、观察者(Observer)和责任链(Chain of Responsibility)。 .NET Framework 4.5 是微软的一个强大的开发平台,支持多种编程语言,并提供了大量的类库和服务,...

    JAVA design pattern-java设计模式

    如命令(Command)、解释器(Interpreter)、迭代器(Iterator)、中介者(Mediator)、备忘录(Memento)、观察者(Observer)、状态(State... Method)、访问者(Visitor)和责任链(Chain of Responsibility)...

Global site tag (gtag.js) - Google Analytics