設計模式(十四)—— 職責鏈模式

模式簡介


使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這些對象連成一個鏈,並沿着鏈傳遞該請求,直到有一個對象處理它爲止。數組

職責鏈模式是一種行爲型模式,它包括命令對象以及一系列處理對象。每一個處理對象決定它可以處理哪些命令對象,將不能處理的命令對象傳遞至職責鏈中的下一個處理對象。app

想象一下公司的OA系統,提交請假單時系統會根據你的請假天數將申請單"交給"不一樣的人去審批,例如請假1-2天,只須要Team Leader審批,3-5天須要Manager審批,大於5天須要Director審批,這就造成了一個職責鏈。假如你要請假1個月,系統首先把請求傳遞給Leader對象,Leader對象發現本身沒法處理這個請求,將請求傳遞給Manager對象,Manager也沒法處理,再傳遞給Director。ide

結構說明


角色說明

  • Handler

定義一個處理請求的接口。this

  • ConcreteHandler

實際負責處理請求的類。若是符合條件,處理該請求,不然轉發給後續的ConcreteHandler。spa

結構代碼

聲明抽象類Handler,定義一個處理請求的接口。code

public abstract class Handler
{
    protected Handler _successor;
    public void SetSuccessor(Handler successor)
    {
        this._successor = successor;
    }
    public abstract void Handle(int request);
}

具體實現類,負責處理請求。ConcreteHanlder1處理reqeust小於等於10的請求,其餘由ConcreteHandler2進行處理。對象

class ConcreteHandler1 : Handler
{
    public override void Handle(int request)
    {
        if (request <= 10)
        {
            Console.WriteLine($"{this.GetType().Name} handled request {request}");
        }
        else if (_successor != null)
        {
            _successor.Handle(request);
        }
    }
}

class ConcreteHandler2 : Handler
{
    public override void Handle(int request)
    {
        if (request > 10)
        {
            Console.WriteLine($"{this.GetType().Name} handled request {request}");
        }
        else if (_successor != null)
        {
            _successor.Handle(request);
        }
    }
}

客戶端調用,設置職責鏈h1 -> h2,依次對requests數組中的元素進行處理。blog

class Program
{
    static void Main(string[] args)
    {
        ConcreteHandler1 h1 = new ConcreteHandler1();
        ConcreteHandler2 h2 = new ConcreteHandler2();
        h1.SetSuccessor(h2);
        int[] requests = { 1, 4, 5, 11, 24 };
        foreach (var request in requests)
        {
            h1.Handle(request);
        }
        Console.ReadLine();
    }
}

輸出結果:接口

工做原理

當用戶提交一個請求,請求將沿着職責鏈依次傳遞知道有一個ConcreteHandler對象負責處理它。get

示例分析


回到本篇開頭請假申請的示例,本節咱們將經過職責鏈模式來實現它,首先建立請求類LeaveReqeust,包含申請人以及申請天數,

class LeaveRequest
{
    public string Applicant { get; set; }
    public int Days { get; set; }
}

聲明抽象類Approver,定義一個處理請求的抽象方法Approve。

abstract class Approver
{
    protected Approver _successor;
    public void SetSuccessor(Approver successor)
    {
        _successor = successor;
    }

    public abstract void Approve(LeaveRequest request);
}

聲明Leader、Manager、Director三個實際處理請求的類。

class Leader : Approver
{
    public override void Approve(LeaveRequest request)
    {
        if (request.Days <= 2)
        {
            Console.WriteLine($"{this.GetType().Name} approved request {request.Applicant},{request.Days}");
        }
        else if (_successor != null)
        {
            _successor.Approve(request);
        }
    }
}

class Manager : Approver
{
    public override void Approve(LeaveRequest request)
    {
        if (request.Days <= 5)
        {
            Console.WriteLine($"{this.GetType().Name} approved request {request.Applicant},{request.Days}");
        }
        else if (_successor != null)
        {
            _successor.Approve(request);
        }
    }
}

class Director : Approver
{
    public override void Approve(LeaveRequest request)
    {
        Console.WriteLine($"{this.GetType().Name} approved request {request.Applicant},{request.Days}");
    }
}

客戶端調用,建立職責鏈leader->manager->director,接着建立3個請求傳遞給職責鏈,依次處理。

class Program
{
    static void Main(string[] args)
    {
        Leader leader = new Leader();
        Manager manager = new Manager();
        Director director = new Director();
        leader.SetSuccessor(manager);
        manager.SetSuccessor(director);

        LeaveRequest jack = new LeaveRequest
        {
            Applicant = "Jack",
            Days = 2
        };

        LeaveRequest tom = new LeaveRequest
        {
            Applicant = "Tom",
            Days = 30
        };

        LeaveRequest mike = new LeaveRequest
        {
            Applicant = "Mike",
            Days = 4
        };

        leader.Approve(jack);
        leader.Approve(tom);
        leader.Approve(mike);
        Console.ReadLine();
    }
}

輸出結果:

適用場景


  • 由多個對象處理一個請求,在運行時肯定具體使哪一個對象進行處理

  • 職責鏈能夠動態指定

相關文章
相關標籤/搜索