Java设计模式之 责任链模式

Java设计模式 - 责任链模式

责任链模式应用场景:

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止.适合使用责任链模式的情景如下:有许多对象可以处理用户的请求,应用程序可以自动确定谁处理用户请求;希望在用户不必明确指定接收者的情况下,向多个接收者提交一个请求,程序希望动态定制可处理用户请求的对象集合.

源代码下载地址:

https://github.com/godlikecheng/Duty_Model/

责任链模式的实现方式:

(1)请求类Request:

package duty_model_01;
/**
 * 请求类Request
 * @author 张宜成
 */
public class Request {
	// 成员变量day代表请假的天数
	int day;
	Request(int day) {
		this.day = day;
	}
}

(2)抽象处理者类Handler

package duty_model_01;
/**
 * 抽象处理者类Handler
 * @author 张宜成
 */
public abstract class Handler {
	private Handler next;  //定义后继处理者变量

	public Handler getNext() {
		return next;
	}

	public void setNext(Handler next) {
		this.next = next;
	}
	
	public abstract boolean handle(Request req);  // 定义抽象方法,子类要重写
}

(3)三个具体处理者类

package duty_model_01;
/**
 * 三个具体处理者类 - 组长类
 * @author 张宜成
 */
public class ZuZhang extends Handler {

	static int limit = 1;
	
	public boolean handle(Request req) {
		if(req.day <= limit) {
			System.out.println("ZuZhang agree the request!");
			return true;
		}
		
		return getNext().handle(req);
	}

}
package duty_model_01;
/**
 * 三个具体处理者类
 * 
 * @author 张宜成
 */
public class ZhuRen extends Handler {

	static int limit = 2;

	public boolean handle(Request req) {
		if (req.day <= limit) {
			System.out.println("ZhuRen agrees the request !!");
			return true;
		}
		return getNext().handle(req);
	}

}
package duty_model_01;
/**
 * 三个具体处理者类 -> 经理类
 * 
 * 组长 主任给员工假是有权限的,分别是1天和2天,因此在各自的handle()方法中是有if判断语句的;
 * 经理原则上可以批准 > 2 的任意假期期间,没有上限,因此在handle()方法中无if判断语句
 * 
 */
public class JingLi extends Handler {

	public boolean handle(Request req) {
		System.out.println("JingLi agree the request !!");
		return true;
	}
	
}

(4)生成责任链前后顺序关系

package duty_model_01;
/**
 * 生成责任链前后顺序关系类
 * 
 * 从createChain()方法中可看出,责任链首节是组长对象,后继节点是主任对象,主任对象的后继节是经理对象.
 * handle()方法负责把请求Request对象req放入责任链首节点中并开始运行.
 * 
 * @author 张宜成
 */
public class MyChain {
	private Handler one = new ZuZhang();
	private Handler two = new ZhuRen();
	private Handler three = new JingLi();
	
	public void createChain() {
		one.setNext(two);
		two.setNext(three);
	}
	
	public void handle(Request req) {
		one.handle(req);
	}
	
}

(5)测试类

package duty_model_01;
/**
 * 测试类
 * @author 张宜成
 */
public class Test {
	public static void main(String[] args) {
		Request req = new Request(2);  // 定义请假1天的请求对象
		MyChain mc = new MyChain();
		mc.createChain();  //创建责任链
		mc.handle(req);  // 将请求放入链中
	}
	
}

运行结果:


反射的作用:

 * 很明显.从编制的MyChain类可以看出:所形成的责任链是刚性的,若需求分析发生了变化,链中需增加
 * 或者减少节点,我们必须重新修改MyChain类,以事应需求分析发展的需要,那么,能否不修改程序,而能又满足需求分析的
 * 变化呢? 答案是可以的,那就是"配置文件 + 反射" 技术.

package duty_model_01;

import java.io.FileInputStream;
import java.util.Properties;

/**
 * @author 张宜成
 *
 */
public class MyChain2 {
	private Handler handle[];
	public void createChain() {
		try {
			String path = this.getClass().getResource("/").getPath();
			FileInputStream in = new FileInputStream(path + "one/myconfig.txt");  // 读取配置文件
			Properties p = new Properties();
			p.load(in);
			String s = p.getProperty("chain");
			String unit[] = s.split(",");  // 按","拆分,得各责任链类
			int n = unit.length;
			handle = new Handler[n];  // 共有n个处理者
			for(int i = 0; i < n; i ++) {
				// 通过反射技术加载各责任链类对象
				handle[i] = (Handler)Class.forName(unit[i]).newInstance();
			}
			for (int i = 0; i < n-1; i ++) {
				handle[i].setNext(handle[i + 1]);  // 设置节点前后关系
			}
			in.close();
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public void handle(Request req) {
		handle[0].handle(req);
	}
}

回调技术

案例:  对英文字符串数据进行如下功能处理:

(1) 全部变成大写字母; (2)去掉所有的空格

(1)请求类

package duty_model_02;
/**
 * 测试类
 * @author 张宜成
 */
public class Test {
	public static void main(String[] args) {
		Request req = new Request("i am a student");  //请求对象
		Response rep = new Response("");  // 响应对象
		Filter one = new OneFilter();  // 定义过滤器1
		Filter two = new TwoFilter();  // 定义过滤器2
		FilterChain fc = new FilterChain();  //定义过滤器容器对象
		fc.addFilter(one);  //添加过滤器1对象
		fc.addFilter(two);  // 添加过滤器2对象
		fc.doFilter(req, rep, fc);  // 进行字符串级联过滤
		System.out.println(rep.rep);  // 输出字符串的过滤结果
		
	}
}
package duty_model_02;

public class Response {
	String rep;
	Response(String rep) {
		this.rep = rep;
	}
}

(2)FilterChain: * 该类主要包含两个功能: * 一是生成了过滤器集合对象;  * 二是实现了回调功能

package duty_model_02;

import java.util.ArrayList;

/**
 * 该类主要包含两个功能:
 * 一是生成了过滤器集合对象;
 * 二是实现了回调功能
 * @author 张宜成
 */
public class FilterChain implements Filter {
	
	ArrayList<Filter> ary = new ArrayList();
	int index = 0;
	
	void addFilter(Filter f) {
		ary.add(f);
	}
	public void doFilter(Request req, Response rep, FilterChain fc) {
		if(index == ary.size())
			return;
		Filter f = ary.get(index);
		index ++;
		f.doFilter(req, rep, fc);
	}
	
}

(3)定义抽象处理者接口Filter

package duty_model_02;
/**
 * 接口类 - 由于本示例相当于过滤字符串功能,因此名称定义为Filter
 * Request代表请求类,包含对字符串的原生封装;
 * Response代表相应类,包含对处理后的结果字符串的封装;
 * FilterChain是过滤器容器类,其对象作为具体处理者必备的回调参数.
 * 
 * 
 * @author 张宜成
 */
public interface Filter {
	void doFilter(Request req, Response rep, FilterChain fc);
}

(4)具体处理者类

package duty_model_02;
/**
 * 英文字符串大写转变为小写
 */
public class OneFilter implements Filter {

	public void doFilter(Request req, Response rep, FilterChain fc) {
		String s = req.req;
		rep.rep = s.toUpperCase();
		fc.doFilter(req, rep, fc);
	}
	
}
package duty_model_02;

/**
 * 去掉所有的空格类
 * @author 张宜成
 */
public class TwoFilter implements Filter {

	public void doFilter(Request req, Response rep, FilterChain fc) {
		String s = rep.rep;
		StringBuffer sbuf = new StringBuffer();
		for (int i = 0; i < s.length(); i++) {
			char ch = s.charAt(i);
			if (ch != ' ') {
				sbuf.append(ch);
			}
		}
		rep.rep = sbuf.toString();
		fc.doFilter(req, rep, fc);
	}

}

测试类:

package duty_model_02;
/**
 * 测试类
 * @author 张宜成
 */
public class Test {
	public static void main(String[] args) {
		Request req = new Request("i am a student");  //请求对象
		Response rep = new Response("");  // 响应对象
		Filter one = new OneFilter();  // 定义过滤器1
		Filter two = new TwoFilter();  // 定义过滤器2
		FilterChain fc = new FilterChain();  //定义过滤器容器对象
		fc.addFilter(one);  //添加过滤器1对象
		fc.addFilter(two);  // 添加过滤器2对象
		fc.doFilter(req, rep, fc);  // 进行字符串级联过滤
		System.out.println(rep.rep);  // 输出字符串的过滤结果
		
	}
}

运行结果:


从上述例子中FilterChain类的doFilter方法可以看出,它实现的其实是回调.若具体处理者花费时间很长,则应用程序就不能执行其他功能了.我们能否实现一种机制,再调用具体处理者执行时,调用者还能完成其他操作?毫无疑问,这要用到多线程技术,即利用多线程技术实现异步回调.

实现多线程技术实现异步回调,只需要将回调技术中的代码进行更改即可.

将上述的 -> FilterChain 更改:

package duty_model_02;

import java.util.ArrayList;

/**
 * 该类主要包含两个功能:
 * 一是生成了过滤器集合对象;
 * 二是实现了回调功能
 * @author 张宜成
 */
public class FilterChain implements Filter {
	
	ArrayList<Filter> ary = new ArrayList();
	int index = 0;
	
	void addFilter(Filter f) {
		ary.add(f);
	}
	public void doFilter(Request req, Response rep, FilterChain fc) {
		if(index == ary.size())
			return;
		Filter f = ary.get(index);
		index ++;
//		f.doFilter(req, rep, fc);
		MyThread th = new MyThread(req,rep,f,fc);
		th.start();
		
	}
}

将req rep f和fc进一步封装成线成MyThreadMyThread对象参数,启动线成实现了异步回调

package duty_model_02;
/**
 * 将req rep f和fc进一步封装成线成MyThreadMyThread对象参数,启动线成实现了异步回调
 * @author 张宜成
 */
public class MyThread extends Thread {
	Request req;
	Response rep;
	Filter f;
	FilterChain fc;
	MyThread(Request req, Response rep, Filter f, FilterChain fc) {
		this.req = req;
		this.rep = rep;
		this.f = f;
		this.fc = fc;
	}
	
	public void run() {
		f.doFilter(req, rep, fc);
	}
	
}

猜你喜欢

转载自blog.csdn.net/qq_40820862/article/details/82656909