劍指33.醜數
阿新 • • 發佈:2020-08-19
一、責任鏈模式介紹
1、定義與型別
為請求建立一個接收此次請求物件的鏈
型別:行為型
2、適用場景
一個請求的處理需要多個物件當中的一個或幾個協作處理
3、優點
請求的傳送者和接收者(請求的處理)解耦
責任鏈可以動態組合
4、缺點
責任鏈太長或者處理時間過長,影響效能
責任鏈有可能過多
5、相關設計模式
責任鏈模式和狀態模式
責任鏈模式中,各個物件並不指定下一個處理物件者是誰,只有客戶端來設定順序和元素,直到被某個責任鏈元素處理或者整個責任鏈結束。
狀態模式是讓每個狀態物件知道下一個狀態物件是誰,在編譯時就設定好了。
二、程式碼示例
模擬場景:釋出課程,課程中需要含有手記和視訊,才能批准;
第一步,先檢查手記,不為空才能批准,否則不批准
第二步,再檢查視訊,不為空才能批准,否則不批准
課程類:
public class Course { private String name; private String article; private String video; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getArticle() { return article; } public void setArticle(String article) { this.article = article; } public String getVideo() { return video; } public void setVideo(String video) { this.video = video; } public Course(String name, String article, String video) { this.name = name; this.article = article; this.video = video; } public Course() { } }
1、v1版本(Appover):
處理抽象類:
public abstract class Appover {
protected Appover appover;
public void setNextAppover(Appover appover){
this.appover = appover;
}
public abstract void deploy(Course course);
}
手記處理類:
public class ArticleAppover extends Appover { @Override public void deploy(Course course) { if (StringUtil.isNotEmpty(course.getArticle())){ System.out.println(course.getName() + " 含有手記, 批准"); if (appover != null){ appover.deploy(course); } else { System.out.println("鏈條結束"); } } else { System.out.println(course.getName() + " 不包含有手記, 不批准,流程結束"); return; } } }
視訊處理類:
public class VideoAppover extends Appover {
@Override
public void deploy(Course course) {
if (StringUtil.isNotEmpty(course.getVideo())){
System.out.println(course.getName() + " 含有視訊, 批准");
if (appover != null){
appover.deploy(course);
} else {
System.out.println("鏈條結束");
}
} else {
System.out.println(course.getName() + " 不包含有視訊, 不批准,流程結束");
return;
}
}
}
測試類:
public class Test {
public static void main(String[] args) {
Appover articleAppover = new ArticleAppover();
Appover videoAppover = new VideoAppover();
articleAppover.setNextAppover(videoAppover);
Course course1 = new Course("責任鏈模式講解", "手記", "視訊");
articleAppover.deploy(course1);
Course course2 = new Course();
course2.setName("設計模式");
articleAppover.deploy(course2);
}
}
輸出:
責任鏈模式講解 含有手記, 批准
責任鏈模式講解 含有視訊, 批准
鏈條結束
設計模式 不包含有手記, 不批准,流程結束
2、v2版本(Handler),(推薦,使用起來更加靈活):
處理抽象類:
public abstract class AbstractHandler {
abstract void doHandler(HandlerChainContext handlerChainContext, Course course); // handler方法
}
處理類上下文(對處理類進行包裝):
/**
* handler上下文,主要負責維護鏈,和鏈的執行
*/
public class HandlerChainContext {
HandlerChainContext next; // 下一個節點
AbstractHandler handler;
public HandlerChainContext(AbstractHandler handler) {
this.handler = handler;
}
void handler(Course course) {
this.handler.doHandler(this, course);
}
/**
* 繼續執行下一個
*/
void runNext(Course course) {
if (this.next != null) {
this.next.handler(course);
} else {
System.out.println("鏈條結束");
}
}
}
手記處理類:
public class ArticleHandler extends AbstractHandler{
@Override
void doHandler(HandlerChainContext handlerChainContext, Course course) {
if (StringUtil.isNotEmpty(course.getArticle())){
System.out.println(course.getName() + " 含有手記, 批准");
// 繼續執行下一個
handlerChainContext.runNext(course);
} else {
System.out.println(course.getName() + " 不包含有手記, 不批准,流程結束");
return;
}
}
}
視訊處理類:
public class VideoHandler extends AbstractHandler {
@Override
void doHandler(HandlerChainContext handlerChainContext, Course course) {
if (StringUtil.isNotEmpty(course.getVideo())){
System.out.println(course.getName() + " 含有視訊, 批准");
// 繼續執行下一個
handlerChainContext.runNext(course);
} else {
System.out.println(course.getName() + " 不包含有視訊, 不批准,流程結束");
return;
}
}
}
鏈路類:
public class PipelineChain {
/**
* 初始化的時候造一個head,作為責任鏈的開始,但是並沒有具體的處理
* 目的就是啟動下一個handler
*/
public HandlerChainContext head = new HandlerChainContext(new AbstractHandler() {
@Override
void doHandler(HandlerChainContext handlerChainContext, Course course) {
handlerChainContext.runNext(course);
}
});
public void requestProcess(Course course) {
this.head.handler(course);
}
public void addLast(AbstractHandler handler) {
HandlerChainContext context = head;
while (context.next != null) {
context = context.next;
}
context.next = new HandlerChainContext(handler);
}
}
測試類:
public class Test {
public static void main(String[] args) {
PipelineChain pipelineChain = new PipelineChain();
// 優點:此處的 ArticleHandler 和 VideoHandler 不需要直接產生關聯
// 即可以直接在中間增加其他 Handler
pipelineChain.addLast(new ArticleHandler());
pipelineChain.addLast(new VideoHandler());
Course course1 = new Course("責任鏈模式講解", "手記", "視訊");
// 發起請求
pipelineChain.requestProcess(course1);
Course course2 = new Course();
course2.setName("設計模式");
// 發起請求
pipelineChain.requestProcess(course2);
}
}
輸出:
責任鏈模式講解 含有手記, 批准
責任鏈模式講解 含有視訊, 批准
鏈條結束
設計模式 不包含有手記, 不批准,流程結束
三、原始碼示例
Servlet中的Filter