今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
title

责任链模式(Chain of responsibility)

定义

责任链模式旨在解耦发出请求的对象和处理请求的对象。它包括一系列处理对象和一个起始点。当一个请求进入这条链时,它沿着链传递,直到有一个对象能够处理该请求,或者请求到达链的末端。

意图

  • 请求者和处理者的解耦: 将发送者与接收者解耦,使得发送者不需要知道请求的具体处理者是谁,以及它们是如何处理请求的。

  • 动态创建对象链: 允许在运行时动态地组织对象链和配置处理对象,增加、删除或重新排列处理对象,从而灵活地修改请求的处理方式。

  • 分发责任: 每个处理对象只负责自己能够处理的请求,将请求发送给适当的处理者,实现责任的分担和职责的分离。

  • 可扩展性和可维护性: 由于责任链模式中的对象链是动态创建的,因此可以方便地扩展和维护。新增处理者或调整处理顺序不需要修改客户端代码。

  • 避免请求的无法处理: 确保每个请求都有一个处理者能够处理,如果当前处理者无法处理请求,可以将其传递给下一个处理者,直至请求被处理。

参与者(角色)

  • Handler(处理者): 定义处理请求的接口,并且通常包含一个指向下一个处理者的引用。该接口通常包含一个处理请求的方法。

  • ConcreteHandler(具体处理者): 实现了处理请求的接口。如果自己能够处理请求,则处理它;否则,将请求传递给链中的下一个处理者。

  • Client(客户端): 创建并发送请求给责任链的起始点。客户端并不需要知道请求是由哪个具体的处理者来处理的。

举例

以员工请假,领导审批为例

类图:

这个例子中对应类的角色如下:

  • Handler(处理者):Leader

  • ConcreteHandler(具体处理者): Manager,GroupLeader,Boss

  • Client(客户端): LeaveRequest
     

Leader类,有名字和下一个领导属性

public abstract class Leader {
	 protected  String name;
	 protected Leader nextLeader;
	 public Leader getNextLeader() {
		return nextLeader;
	}
	public void setNextLeader(Leader nextLeader) {
		this.nextLeader = nextLeader;
	}
	public Leader(String name){
		 this.name =name;
	 }
	public abstract  void handleRequest(LeaveRequest    request);
		
}

 

Manager 

public class Manager extends Leader {

	/**
	 * @param name
	 */
	public Manager(String name) {
		super(name);
	}


	@Override
	public void handleRequest(LeaveRequest request) {
		String name = request.getName();
		String reason = request.getReason();
		int days = request.getDays();
		if (days <= 15) {
			System.out.println(name + "需要请假" + days + "天,请假理由" + reason
					+ "经理同意审批!");
		} else {
			System.out.println("超过15天的假期需要董事长审批!");
			if (this.nextLeader != null) {
				this.nextLeader.handleRequest(request);
			}
		}
	}

}

 

Boss 具体处理者

public class Boss extends Leader {

	/**
	 * @param name
	 */
	public Boss(String name) {
		super(name);
	}
	
	@Override
	public void handleRequest(LeaveRequest request) {
		String name = request.getName();
		String reason = request.getReason();
		int days = request.getDays();
		if (days <= 30) {

			System.out.println(name + "需要请假" + days + "天,请假理由" + reason
					+ " 董事长同意审批!");
		} else {
			System.out.println("我无法处理该请假天数,需要部门商量");
			if (this.nextLeader != null) {
				this.nextLeader.handleRequest(request);
			}else{
				System.out.println("暂时不能请假");
			}
		}
	}

}

 

LeaveRequest,包含请假的参数

public class LeaveRequest {
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getDays() {
		return days;
	}
	public void setDays(int days) {
		this.days = days;
	}
	public String getReason() {
		return reason;
	}
	public void setReason(String reason) {
		this.reason = reason;
	}
	private String name;
	private int days;
	private String reason;
	
}

 

测试

	public static void main(String[] args) {
			Leader groupLeader = new GroupLeader("部门组长");
			Leader  manager = new Manager("部门经理");
			Leader  boss = new Boss("董事长");
			groupLeader.setNextLeader(manager);
			manager.setNextLeader(boss);
			LeaveRequest leaveRequest = new LeaveRequest();
			leaveRequest.setDays(31);
			leaveRequest.setName("张三");
			leaveRequest.setReason("肚子疼");
			groupLeader.handleRequest(leaveRequest);
	}

//output

超过5天的假期需要经理审批
超过15天的假期需要董事长审批!
我无法处理该请假天数,需要部门商量
暂时不能请假

 

优点

  1. 解耦责任者和请求者: 责任链模式使得请求者和处理者之间解耦,请求者不需要知道具体的处理者,而处理者也不需要知道请求的发送者,降低了对象之间的耦合度。

  2. 灵活性和可扩展性: 可以动态地增加或修改处理者,改变处理者之间的连接顺序,或者改变处理者的职责,从而灵活地调整和扩展处理流程。

  3. 单一职责原则: 每个具体处理者都只关注自己负责处理的请求类型,符合单一职责原则,易于维护和修改。

  4. 降低耦合度: 因为每个处理者只需知道自己的后继者,处理者之间的关系松散,易于独立开发、测试和维护。

  5. 可以控制处理顺序: 可以通过调整处理者之间的连接顺序来控制请求的处理顺序,可以按照需求定义处理者的优先级。

缺点

  1. 可能导致请求未被处理: 如果责任链中没有合适的处理者来处理请求,或者所有处理者都没有正确配置,请求可能会到达链的末端而无法被处理。

  2. 性能问题: 如果责任链过长或者处理者选择不当,可能会导致请求在链中传递过程中出现性能问题。

  3. 难以调试: 当责任链比较长时,可能会增加代码的复杂性和难以调试的难度。

 

责任链模式的应用

Netty ChannelPipeline 

通过addLast方法构成一个handler处理链

public class ServerInitializer extends ChannelInitializer<SocketChannel> {


    @Override
    protected void initChannel(SocketChannel ch) {
        ChannelPipeline pipeline = ch.pipeline();
        System.out.println(pipeline.toString());
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new ChunkedWriteHandler());
        pipeline.addLast(new FileUploadHandler());
    }
}
   public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
        final AbstractChannelHandlerContext newCtx;
        synchronized (this) {
            checkMultiplicity(handler);

            newCtx = newContext(group, filterName(name, handler), handler);

            addLast0(newCtx);

            // If the registered is false it means that the channel was not registered on an eventLoop yet.
            // In this case we add the context to the pipeline and add a task that will call
            // ChannelHandler.handlerAdded(...) once the channel is registered.
            if (!registered) {
                newCtx.setAddPending();
                callHandlerCallbackLater(newCtx, true);
                return this;
            }

            EventExecutor executor = newCtx.executor();
            if (!executor.inEventLoop()) {
                callHandlerAddedInEventLoop(newCtx, executor);
                return this;
            }
        }
        callHandlerAdded0(newCtx);
        return this;
    }

    private void addLast0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;
    }

 

 

分享到:

专栏

类型标签

网站访问总量