1. 程式人生 > >Java設計模式十一: 職責鏈模式(Chain of Responsibility)

Java設計模式十一: 職責鏈模式(Chain of Responsibility)

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

類圖:

職責鏈模式的組成:
抽象處理者(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

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