1. 程式人生 > >設計模式-責任鏈模式Chain of Responsibility)

設計模式-責任鏈模式Chain of Responsibility)

一、定義

職責鏈模式是一種物件的行為模式。在職責鏈模式裡,很多物件由每一個物件對其下家的引用而連線起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個物件決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個物件最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任。

1、為請求建立一個接收此次請求物件的鏈

2、型別:行為型

 

二、適用場景

一個請求的處理需要多個物件當中的一個或幾個協作處理

 

三、有點

請求的傳送者和接收者(請求的處理)解耦

責任鏈可以動態的組合

 

四、缺點

責任鏈太長或者處理時間過長,影像效能

責任鏈有可能過多



五、類圖:

職責鏈模式的組成:
抽象處理者(Handler)角色:定義出一個處理請求的介面。如果需要,介面可以定義出一個方法,以設定和返回對下家的引用。這個角色通常由一個抽象類或介面實現。
具體處理者(ConcreteHandle)角色:具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。

六、例項:公司請病假,1天內,專案經理批准;2天內Senior PM批准; 大於兩天,醫院提供病例、假條
public abstract class LeaveBaseHandler
{
    protected LeaveBaseHandler successor;

    public LeaveBaseHandler getSuccessor()
    {
        return successor;
    }

    public void setSuccessor(final LeaveBaseHandler successor)
    {
        this.successor = successor;
    }

    public abstract void requestLeave(int days);
}

public class OneDayLeaveConcreteHandler extends LeaveBaseHandler
{
    @Override
    public void requestLeave(final int days)
    {
        if (days <= 1)
        {
            System.out.println("approve one day leave");
        }
        else
        {
            super.successor.requestLeave(days);
        }

    }

}

public class TwoDaysLeaveConcreteHandler extends LeaveBaseHandler
{
    @Override
    public void requestLeave(final int days)
    {
        if (days > 1 && days <= 2)
        {
            System.out.println("approve 2 days leave");
        }
        else
        {
            super.successor.requestLeave(days);
        }
    }
}

public class MoreThanTwoDaysConcreteHandler extends LeaveBaseHandler
{
    @Override
    public void requestLeave(final int days)
    {
        if (days > 2)
        {
            System.out.println("get the record for leave from hospital");
        }
    }
}

public class Client
{
    private static void requestLeave()
    {
        final LeaveBaseHandler oneDay = new OneDayLeaveConcreteHandler();
        final LeaveBaseHandler twoDays = new TwoDaysLeaveConcreteHandler();
        final LeaveBaseHandler moreThanTwoDays = new MoreThanTwoDaysConcreteHandler();
        oneDay.setSuccessor(twoDays);
        twoDays.setSuccessor(moreThanTwoDays);

        oneDay.requestLeave(1);
        oneDay.requestLeave(2);
        oneDay.requestLeave(3);
    }

    public static void main(final String[] args)
    {
        requestLeave();
    }
}

結果:
approve one day leave
approve 2 days leave
get the record for leave from hospital

如果職責鏈結構比較複雜,會產生很多的記憶體垃圾物件。

 

七、例項2

課程稽核

1、建立批准者類

/**
 * 批准者 2019/1/7.
 */
public abstract class Approver {

    //責任鏈的核心是包含一個自己。 protected可以讓子類獲取到它
    protected Approver approver;


    //設定下一個批准者
    public  void setNextApprover(Approver approver){
        this.approver = approver;
    }

    //釋出課程
    public abstract void deploy(Course course);
}

  

2、建立ArticleApprover 

public class ArticleApprover extends  Approver{
    @Override
    public void deploy(Course course) {
        if(StringUtils.isNotBlank(course.getArticle())){
            System.out.println(course.getName() + "含有Article,批准");
            if(approver != null){
                approver.deploy(course);
            }
        }else{
            System.out.println(course.getName() + "無Article,不批准,流程結束");
            return;
        }


    }
}

 

3、建立VideoApprover  

public class VideoApprover extends  Approver{
    @Override
    public void deploy(Course course) {
        if(StringUtils.isNotBlank(course.getVideo())){
            System.out.println(course.getName() + "含有Video,批准");
            if(approver != null){
                approver.deploy(course);
            }
        }else{
            System.out.println(course.getName() + "無Video,不批准,流程結束");
            return;
        }


    }
}

  

4、建立課程Course

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;
    }

    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + '\'' +
                ", article='" + article + '\'' +
                ", video='" + video + '\'' +
                '}';
    }
}

  

5、建立測試類

public class Test {
    public static void main(String[] args) {
        //稽核員稽核article
        Approver articleApprover = new ArticleApprover();
        //稽核員稽核video
        Approver videoApprover = new VideoApprover();

        Course course = new Course();
        course.setName("設計模式");
        course.setArticle("設計模式Article");
        course.setVideo("設計模式Video");

        articleApprover.setNextApprover(videoApprover);

        articleApprover.deploy(course);
    }
}

  

6、輸出結果

 

 

 

一、定義

職責鏈模式是一種物件的行為模式。在職責鏈模式裡,很多物件由每一個物件對其下家的引用而連線起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個物件決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個物件最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任。

1、為請求建立一個接收此次請求物件的鏈

2、型別:行為型

 

二、適用場景

一個請求的處理需要多個物件當中的一個或幾個協作處理

 

三、有點

請求的傳送者和接收者(請求的處理)解耦

責任鏈可以動態的組合

 

四、缺點

責任鏈太長或者處理時間過長,影像效能

責任鏈有可能過多



五、類圖:

職責鏈模式的組成:
抽象處理者(Handler)角色:定義出一個處理請求的介面。如果需要,介面可以定義出一個方法,以設定和返回對下家的引用。這個角色通常由一個抽象類或介面實現。
具體處理者(ConcreteHandle)角色:具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。

六、例項:公司請病假,1天內,專案經理批准;2天內Senior PM批准; 大於兩天,醫院提供病例、假條
public abstract class LeaveBaseHandler
{
    protected LeaveBaseHandler successor;

    public LeaveBaseHandler getSuccessor()
    {
        return successor;
    }

    public void setSuccessor(final LeaveBaseHandler successor)
    {
        this.successor = successor;
    }

    public abstract void requestLeave(int days);
}

public class OneDayLeaveConcreteHandler extends LeaveBaseHandler
{
    @Override
    public void requestLeave(final int days)
    {
        if (days <= 1)
        {
            System.out.println("approve one day leave");
        }
        else
        {
            super.successor.requestLeave(days);
        }

    }

}

public class TwoDaysLeaveConcreteHandler extends LeaveBaseHandler
{
    @Override
    public void requestLeave(final int days)
    {
        if (days > 1 && days <= 2)
        {
            System.out.println("approve 2 days leave");
        }
        else
        {
            super.successor.requestLeave(days);
        }
    }
}

public class MoreThanTwoDaysConcreteHandler extends LeaveBaseHandler
{
    @Override
    public void requestLeave(final int days)
    {
        if (days > 2)
        {
            System.out.println("get the record for leave from hospital");
        }
    }
}

public class Client
{
    private static void requestLeave()
    {
        final LeaveBaseHandler oneDay = new OneDayLeaveConcreteHandler();
        final LeaveBaseHandler twoDays = new TwoDaysLeaveConcreteHandler();
        final LeaveBaseHandler moreThanTwoDays = new MoreThanTwoDaysConcreteHandler();
        oneDay.setSuccessor(twoDays);
        twoDays.setSuccessor(moreThanTwoDays);

        oneDay.requestLeave(1);
        oneDay.requestLeave(2);
        oneDay.requestLeave(3);
    }

    public static void main(final String[] args)
    {
        requestLeave();
    }
}

結果:
approve one day leave
approve 2 days leave
get the record for leave from hospital

如果職責鏈結構比較複雜,會產生很多的記憶體垃圾物件。

 

七、例項2

課程稽核

1、建立批准者類

/**
 * 批准者 2019/1/7.
 */
public abstract class Approver {

    //責任鏈的核心是包含一個自己。 protected可以讓子類獲取到它
    protected Approver approver;


    //設定下一個批准者
    public  void setNextApprover(Approver approver){
        this.approver = approver;
    }

    //釋出課程
    public abstract void deploy(Course course);
}

  

2、建立ArticleApprover 

public class ArticleApprover extends  Approver{
    @Override
    public void deploy(Course course) {
        if(StringUtils.isNotBlank(course.getArticle())){
            System.out.println(course.getName() + "含有Article,批准");
            if(approver != null){
                approver.deploy(course);
            }
        }else{
            System.out.println(course.getName() + "無Article,不批准,流程結束");
            return;
        }


    }
}

 

3、建立VideoApprover  

public class VideoApprover extends  Approver{
    @Override
    public void deploy(Course course) {
        if(StringUtils.isNotBlank(course.getVideo())){
            System.out.println(course.getName() + "含有Video,批准");
            if(approver != null){
                approver.deploy(course);
            }
        }else{
            System.out.println(course.getName() + "無Video,不批准,流程結束");
            return;
        }


    }
}

  

4、建立課程Course

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;
    }

    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + '\'' +
                ", article='" + article + '\'' +
                ", video='" + video + '\'' +
                '}';
    }
}

  

5、建立測試類

public class Test {
    public static void main(String[] args) {
        //稽核員稽核article
        Approver articleApprover = new ArticleApprover();
        //稽核員稽核video
        Approver videoApprover = new VideoApprover();

        Course course = new Course();
        course.setName("設計模式");
        course.setArticle("設計模式Article");
        course.setVideo("設計模式Video");

        articleApprover.setNextApprover(videoApprover);

        articleApprover.deploy(course);
    }
}

  

6、輸出結果