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.

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值