常见的设计模式之责任链模式

概念

责任链模式(Chain of Responsibility Pattern)是将链中的每一个节点看做一个对象,每个节点处理的请求均不相同,且内部维护下一节点对象。当一个请求从链式的首段发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止。这种类型的设计模式属于行为型模式。
责任链模式主要包含两种角色:

  • 抽象处理者(Handle):定义一个处理的方法,并维护下一个处理节点Handle对象的引用;
  • 具体处理者(ConcreteHandle):对请求进行处理,如果不感兴趣,则进行转发。

实现

接下来以登录验证为例

1.创建抽象处理者

public abstract class Handle {
    protected Handle chain;

    public void next(Handle handle){
        this.chain=handle;
    }

    public abstract void doHandle(Member member);
}

2.具体处理者

public class ValidateHadle extends Handle {
    @Override
    public void doHandle(Member member) {
        if("".equals(member.getName())||"".equals(member.getPwd())){
            System.out.println("用户名或密码为空");
            return;
        }
        System.out.println("用户名密码格式校验完毕");
        chain.doHandle(member);
    }
}
public class LoginHandle extends Handle {
    @Override
    public void doHandle(Member member) {
        System.out.println("登陆成功");
        chain.doHandle(member);
    }
}
public class AuthHandle extends Handle {
    @Override
    public void doHandle(Member member) {
        System.out.println("欢迎管理员!");
    }
}

3.测试

public class ChainTest {
    public static void main(String[] args) {
        Handle validateHandle=new ValidateHadle();
        Handle loginHandle=new LoginHandle();
        Handle authHandle=new AuthHandle();
        validateHandle.next(loginHandle);
        loginHandle.next(authHandle);
        validateHandle.doHandle(new Member("tom","123"));
    }
}

运行结果:
在这里插入图片描述

使用场景

  • 对个对象处理同一个请求,但具体由哪个对象处理是在运行时动态决定
  • 在不明确指定接受者的情况下,向多个对象中的一个提交请求
  • 可动态指定一组对象处理请求

在Spring框架中的运用

在JDK中,有一个非常常见的类Filter

public interface Filter {
    public void init(FilterConfig filterConfig) throws ServletException;
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;
    public void destroy();

}

这个Filter 接口非常简单,相当于责任链中的Handle抽象角色。再来看一下doFilter方法中最后一个参数FilterChain 类

public interface FilterChain {
    public void doFilter(ServletRequest request, ServletResponse response)
            throws IOException, ServletException;

}

只定义了一个doFilter方法,那他们是怎么串联成链的呢?我们来看Spring的实现MockFilterChain类

public class MockFilterChain implements FilterChain {

	private ServletRequest request;

	private ServletResponse response;

	private final List<Filter> filters;

	private Iterator<Filter> iterator;
	public MockFilterChain() {
		this.filters = Collections.emptyList();
	}
	public MockFilterChain(Servlet servlet) {
		this.filters = initFilterList(servlet);
	}
	public MockFilterChain(Servlet servlet, Filter... filters) {
		Assert.notNull(filters, "filters cannot be null");
		Assert.noNullElements(filters, "filters cannot contain null values");
		this.filters = initFilterList(servlet, filters);
	}

	private static List<Filter> initFilterList(Servlet servlet, Filter... filters) {
		Filter[] allFilters = ObjectUtils.addObjectToArray(filters, new ServletFilterProxy(servlet));
		return Arrays.asList(allFilters);
	}
	public ServletRequest getRequest() {
		return this.request;
	}
	public ServletResponse getResponse() {
		return this.response;
	}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
		Assert.notNull(request, "Request must not be null");
		Assert.notNull(response, "Response must not be null");
		Assert.state(this.request == null, "This FilterChain has already been called!");

		if (this.iterator == null) {
			this.iterator = this.filters.iterator();
		}

		if (this.iterator.hasNext()) {
			Filter nextFilter = this.iterator.next();
			nextFilter.doFilter(request, response, this);
		}

		this.request = request;
		this.response = response;
	}
}

它把链条的所有Filter放到list中,然后再调用doFilter方法是进行迭代List,也就是说List中的Filter会顺序执行
UML类图如下:
在这里插入图片描述

总结

优点

  1. 将请求与处理解耦
  2. 简化了对象。使得对象不需要知道链的结构
  3. 链路结构灵活,可以通过改变链路结构次序,动态的新增或删除责任
  4. 易于扩展新的请求处理类

缺点

  1. 责任链过长,会导致处理时间过长,从而影响整体性能
  2. 如果节点对象存在循环引用,会造成死循环,导致系统崩溃
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值