Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> java/android 設計模式學習筆記(15)---責任鏈模式

java/android 設計模式學習筆記(15)---責任鏈模式

編輯:關於Android編程

這篇博客我們來介紹一下責任鏈模式(Chain-of-responsibility Pattern),責任聯模式又稱為職責鏈模式,是行為型設計模式之一。顧名思義,責任鏈模式中存在一個鏈式結構,多個節點首尾相連,每個節點都可以被拆開再連接,因此,鏈式結構具有很好的靈活性。將這樣一種結構應用於編程領域,將每一個節點看作是一個對象,每一個對象擁有不同的處理邏輯,將一個請求從鏈式的首段發出,沿著鏈的路徑依次傳遞給每一個節點對象,直至有對象處理這個請求為止,這就是責任鏈或者職責鏈的通俗定義。

特點

使多個對象都有機會處理請求,從而避免了請求的發送者和接收者之間的耦合關系,將這些對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有對象處理它為止。
  責任鏈模式的使用場景:

多個對象可以處理統一請求,但具體由哪個對象處理則在運行時動態決定;在請求處理者不明確的情況下向多個對象中的一個提交一個請求;需要動態指定一組對象處理請求。

 

UML類圖

責任鏈模式的 uml 圖如下所示:
  這裡寫圖片描述
責任鏈模式有兩大角色:

Handler:抽象處理者角色,聲明一個請求處理的方法,並在其中保持對下一個處理節點 Hanlder 對象的引用;ConcreteHandler:具體處理者角色,對請求進行處理,如果不能處理則將該請求轉發給下一個節點上的處理對象。對於請求 Request 來說,在大多數情況下,責任鏈中的請求和對應的處理規則是不盡相同的,在這種情況下可以將請求進行封裝,同時對請求的處理規則也進行封裝作為一個獨立的對象,如上圖所示。據此可以寫出通用代碼,首先是 Handler 角色:
AbstractHandler.class

 

public abstract class AbstractHandler {
    protected AbstractHandler nextHandler;

    public final void handleRequest(AbstractRequest request) {
        if (getHandlerLevel() == request.getLevel()) {
            handle(request);
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.print("there is no handler that can handle this request");
            }
        }
    }

    protected abstract int getHandlerLevel();

    protected abstract void handle(AbstractRequest request);
}

ConcreteHandler1.class

public class ConcreteHandler1 extends AbstractHandler{
    @Override
    protected int getHandlerLevel() {
        return 1;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.print("ConcreteHandler1 handle this request : " + request.getContent() + "\n");
    }
}

ConcreteHandler2.class

public class ConcreteHandler2 extends AbstractHandler{
    @Override
    protected int getHandlerLevel() {
        return 2;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.print("ConcreteHandler2 handle this request : " + request.getContent() + "\n");
    }
}

然後是請求角色:
AbstractRequest.class

public abstract class AbstractRequest {

    private Object object;

    public AbstractRequest(Object object) {
        this.object = object;
    }

    public Object getContent() {
        return object;
    }

    public abstract int getLevel();
}

ConcreteRequest1.class

public class ConcreteRequest1 extends AbstractRequest{

    public ConcreteRequest1(Object object) {
        super(object);
    }

    @Override
    public int getLevel() {
        return 1;
    }
}

ConcreteRequest2.class

public class ConcreteRequest2 extends AbstractRequest{

    public ConcreteRequest2(Object object) {
        super(object);
    }

    @Override
    public int getLevel() {
        return 2;
    }
}

最後客戶端測試代碼:

public class Client {
    public static void main(String[] args) {
        AbstractHandler handler1 = new ConcreteHandler1();
        AbstractHandler handler2 = new ConcreteHandler2();
        handler1.nextHandler = handler2;

        AbstractRequest request1 = new ConcreteRequest1("request1");
        AbstractRequest request2 = new ConcreteRequest2("request2");

        handler1.handleRequest(request1);
        handler1.handleRequest(request2);
    }
}

結果如下:
這裡寫圖片描述

示例與源碼

其實責任鏈模式在實際項目過程中遇到的非常多,Android 和 Java 源碼也一樣,舉幾個簡單的例子:

ViewGroup 和 View 中 touch 事件的分發,子 View 的 onTouchEvent 返回 true 代碼消費該事件並不再傳遞,false 代表不消費並且傳遞到父 ViewGroup 去處理,這些樹形結構的子 View 就是責任鏈上一個個處理對象;OrderedBroadcast,廣播的每一個接收者按照優先級依次接受消息,如果處理完成之後可以調用 abortBroadcast 終止廣播,不是自己處理的就可以傳遞給下一個處理者;try-catch語句,每一個 catch 根據 Exception 類型進行匹配,形成一個責任鏈,如果有一個 catch 語句與該 Exception 符合,這個 Exception 就交由給它進行處理,之後所有 catch 語句都不會再次執行。
  我們這就以 wiki 上的代碼為例:每個人都有一個支出審批的額度,超過審批額度之後將會傳遞給下一個審批人,直到最後:
審批人相關類

 

public abstract class PurchasePower {
    protected static final double BASE = 500;
    protected PurchasePower successor;

    abstract protected double getAllowable();
    abstract protected String getRole();

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

    public void processRequest(PurchaseRequest request){
        if (request.getAmount() < this.getAllowable()) {
            System.out.println(this.getRole() + " will approve $" + request.getAmount());
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}
public class ManagerPPower extends PurchasePower {

    protected int getAllowable(){
        return BASE*10;
    }

    protected String getRole(){
        return "Manager";
    }
}

public class DirectorPPower extends PurchasePower {

    protected int getAllowable(){
        return BASE*20;
    }

    protected String getRole(){
        return "Director";
    }
}

public class VicePresidentPPower extends PurchasePower {

    protected int getAllowable(){
        return BASE*40;
    }

    protected String getRole(){
        return "Vice President";
    }
}

public class PresidentPPower extends PurchasePower {

    protected int getAllowable(){
        return BASE*60;
    }

    protected String getRole(){
        return "President";
    }
}

審批類

public class PurchaseRequest {
    private double amount;
    private String purpose;

    public PurchaseRequest(double amount, String purpose) {
        this.amount = amount;
        this.purpose = purpose;
    }

    public double getAmount() {
        return amount;
    }
    public void setAmount(double amt)  {
        amount = amt;
    }

    public String getPurpose() {
        return purpose;
    }
    public void setPurpose(String reason) {
        purpose = reason;
    }
}

最後是客戶端的測試代碼:

public class CheckAuthority {
    public static void main(String[] args) {
        ManagerPPower manager = new ManagerPPower();
        DirectorPPower director = new DirectorPPower();
        VicePresidentPPower vp = new VicePresidentPPower();
        PresidentPPower president = new PresidentPPower();
        manager.setSuccessor(director);
        director.setSuccessor(vp);
        vp.setSuccessor(president);

        // Press Ctrl+C to end.
        try {
            while (true) {
                System.out.println("Enter the amount to check who should approve your expenditure.");
                System.out.print(">");
                double d = Double.parseDouble(new BufferedReader(new InputStreamReader(System.in)).readLine());
                manager.processRequest(new PurchaseRequest(d, "General"));
           }
        } catch(Exception e) {
            System.exit(1);
        }
    }
}

代碼簡潔明了,都應該能看懂。

總結

責任鏈模式的優點顯而易見,可以對請求者和處理者關系解耦,提高代碼的靈活性,通過改變鏈內的成員或調動他們的次序,允許你動態地新增或者刪除職責;但是責任鏈模式最大的缺點在於對鏈中請求處理者的遍歷,如果處理者太多那麼必定會影響性能,特別是在一些遞歸調用中,而且不容易觀察運行時的特征,有礙於除錯。
  很多資料中會介紹純和不純的責任鏈模式,在標准的責任鏈模式中,責任鏈上的一個節點只允許有兩個行為:處理或者推給下個節點處理,而不允許處理完之後又推給下個節點,前者被很多資料稱為純的責任鏈模式,而後者被稱為不純的責任鏈模式。其實在實際的系統裡,純的責任鏈很難找到。如果堅持責任鏈不純便不是責任鏈模式,那麼責任鏈模式便不會有太大意義了。

源碼下載

https://github.com/zhaozepeng/Design-Patterns/tree/master/ChainOfResponsibilityPattern

 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved