1. 程式人生 > 實用技巧 >C++面向物件入門(十四)類物件成員物件和成員函式的分離儲存

C++面向物件入門(十四)類物件成員物件和成員函式的分離儲存

一、責任鏈模式介紹

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