設計模式-職責鏈模式(Reposibility)以及在JDK類庫中的應用

職責鏈模式

定義

使多個對象都可以處理一個請求,將這個對象連成一條鏈,並沿着這條鏈傳遞該請求,直到其中某個對象可以處理它爲止。

結構

抽象處理類:它持有自身的一個引用,定義了一個用來處理請求的接口

具體處理類:實現了抽象處理類的接口方法,在方法內部判斷是否讓其處理請求還是放到下一個處理類來處理。

類圖

個人理解:職責鏈模式的思想是複合+轉發的方式實現的,只不過這次複合的對象是它本身,通過持有自身的引用可以使得處理類形成一個鏈,在處理方法內部判斷是否讓下一個處理類類處理還是自身來處理。

意圖:

抽象處理類:

public abstract class Handler {

	public Handler chain;

	public void setChain(Handler chain) {
		this.chain = chain;
	}
	
	public abstract void handleRequest(int request);
	
}

具體處理類:

public class ConcreteHandlerA extends Handler {

	@Override
	public void handleRequest(int request) {
		if(request > 0 && request <= 10){
			System.out.println("執行A處理方法");
		} else if (chain != null) {
			chain.handleRequest(request);
		}
	}
}
public class ConcreteHandlerB extends Handler {

	@Override
	public void handleRequest(int request) {
		if(request > 10 && request <= 20){
			System.out.println("執行B處理方法");
		} else if (chain != null) {
			chain.handleRequest(request);
		}
	}
}
public class ConcreteHandlerC extends Handler {

	@Override
	public void handleRequest(int request) {
		if(request > 20){
			System.out.println("執行C處理方法");
		}
	}

}

測試類:

	
	public static void main(String[] args) {
		Handler handlerA = new ConcreteHandlerA();
		Handler handlerB = new ConcreteHandlerB();
		Handler handlerC = new ConcreteHandlerC();
		handlerA.setChain(handlerB);
		handlerB.setChain(handlerC);
		handlerA.handleRequest(5);
		handlerA.handleRequest(11);
		handlerA.handleRequest(30);
	}
	

測試結果:

案例

我們以員工申請請假需要經過領導審批爲例。組長、總監、經理作爲處理審批申請的具體處理類,它們各自持有自身的引用,通過請求中請假天數判斷由誰來處理審批流程。

抽象處理類:

public abstract class AbstractHandler {

	public AbstractHandler chain;
	
	public void setChain(AbstractHandler chain) {
		this.chain = chain;
	}

	public abstract void handleRequest(int request);
	
}

組長處理類:

public class TeamLeaderHandler extends AbstractHandler {

	@Override
	public void handleRequest(int request) {
		if(request>0&&request<=2){
			System.out.println("組長同意請假"+request+"天");
		}else if(chain!=null){
			chain.handleRequest(request);
		}
	}

}

總監處理類:

public class DirectorHandler extends AbstractHandler {

	@Override
	public void handleRequest(int request) {
		if(request>2&&request<=5){
			System.out.println("總監同意請假"+request+"天");
		}else if(chain!=null){
			chain.handleRequest(request);
		}
	}

}

經理處理類:

public class ManagerHandler extends AbstractHandler{

	@Override
	public void handleRequest(int request) {
		if(request>5){
			System.out.println("經理同意請假"+request+"天");
		}
	}

}

測試類:

	
	public static void main(String[] args) {
		AbstractHandler teamLeader = new TeamLeaderHandler();
		AbstractHandler director = new DirectorHandler();
		AbstractHandler manager = new ManagerHandler();
		teamLeader.setChain(director);
		director.setChain(manager);
		teamLeader.handleRequest(1);
		teamLeader.handleRequest(3);
		teamLeader.handleRequest(15);
	}
	

測試結果:

優點

1.新增具體處理類方便靈活。

2.將請求的發送者(即客戶端)和請求的接受者(處理類)解耦合。

缺點

可能出現請求無法被處理的情況。

JDK類庫中的職責鏈模式

java.util.loggingLogger#log(LogRecord ld)(暫時還不明白這個爲什麼會使職責鏈模式!

javax.servlet.Filter#doFilter(req,rep)

典型的例子是struts2的核心過濾器:StrutsPrepareAndExecuteFilter

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        try {
            prepare.setEncodingAndLocale(request, response);
            prepare.createActionContext(request, response);
            prepare.assignDispatcherToThread();
            if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
                chain.doFilter(request, response);
            } else {
                request = prepare.wrapRequest(request);
                ActionMapping mapping = prepare.findActionMapping(request, response, true);
                if (mapping == null) {
                    boolean handled = execute.executeStaticResourceRequest(request, response);
                    if (!handled) {
                        chain.doFilter(request, response);
                    }
                } else {
                    execute.executeAction(request, response, mapping);
                }
            }
        } finally {
            prepare.cleanupRequest(request);
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章