1. 程式人生 > 其它 >責任鏈模式 -- 讓一個以上的物件有機會能夠處理某個請求

責任鏈模式 -- 讓一個以上的物件有機會能夠處理某個請求

技術標籤:設計模式設計模式責任鏈模式

責任鏈模式 – 讓一個以上的物件有機會能夠處理某個請求

責任鏈的優點

  1. 降低耦合度。它將請求的傳送者和接收者解耦;
  2. 簡化了物件。使得物件不需要知道鏈的結構;
  3. 增強給物件指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任;
  4. 增加新的請求處理類很方便。

責任鏈的缺點:

  1. 請求沒有明確的接收者,不能保證它一定會被處理,該請求可能一直到鏈的末端都得不到處理;
  2. 對於比較長的職責鏈,請求的處理可能涉及到多個處理物件,系統性能將受到一定影響,而且在進行程式碼除錯時不太方便,可能會造成迴圈呼叫

責任鏈2種形式:
純責任鏈模式和不純的責任鏈模式。

如果一個類要麼承擔責任處理請求要麼將請求踢給下一個皮球,則被稱為純責任鏈模式;如果一個類承擔了一部分責任,還將請求踢給下一個皮球,則被稱為不純的責任鏈模式。純的責任鏈模式的實際例子很難找到,一般看到的例子均是不純的責任鏈模式的實現。

使用場景舉例:

如點選廣告跳轉。
現有如下規則:點選廣告時先判斷是否滿足條件A,如果滿足A,則先嚐試用A方式跳轉,若A方式跳轉失敗,則再嘗試B方式。

程式碼舉例:
抽象基類: Jump.java
提供抽象方法, jump跳轉,各子類根據規則各自實現不同的邏輯

public abstract class Jump {
    private Jump mNext;
abstract boolean jump(Activity activity, MimoAdInfo adInfo); public void setNext(Jump next) { this.mNext = next; } protected void onSuccess(MimoAdInfo adInfo) { } protected void onFail(MimoAdInfo adInfo) { } public final boolean start(Activity activity,
MimoAdInfo adInfo) { boolean success = jump(activity, adInfo); if (success) { onSuccess(adInfo); return true; } if (mNext != null) { return mNext.start(activity, adInfo); } onFail(adInfo); return false; } }

子類: DeepLinkJump.java

public class DeepLinkJump extends Jump{
    @Override
    boolean jump(Activity activity, MimoAdInfo adInfo) {
        if (adInfo != null && !TextUtils.isEmpty(adInfo.mDeepLink)) {
            try {
                final Uri contentUrl = Uri.parse(adInfo.mDeepLink);
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                intent.setData(contentUrl);
                MimoAdManager.get().trackLauchStart(adInfo);
                boolean success = IntentUtils.startActivity(activity, intent);
                return success;
            } catch (Exception e) {
                return false;
            }
        }
        return false;
    }

    @Override
    protected void onSuccess(MimoAdInfo adInfo) {
        MimoAdManager.get().trackLauchSuccess(adInfo);
    }

    @Override
    protected void onFail(MimoAdInfo adInfo) {
        MimoAdManager.get().trackLauchFail(adInfo);
    }
}

子類:LandingPageJump.java

public class LandingPageJump extends Jump{
    @Override
    public boolean jump(Activity activity, MimoAdInfo adInfo) {
        if (adInfo != null && !TextUtils.isEmpty(adInfo.mLandingPageUrl)) {
            try {
                if (adInfo.mLandingPageUrl.startsWith("http://") || adInfo.mLandingPageUrl.startsWith("https://")) {
                    LandingPageHelper.land(adInfo.mLandingPageUrl);
                } else {
                    final Uri contentUrl = Uri.parse(adInfo.mLandingPageUrl);
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_VIEW);
                    intent.setData(contentUrl);
                    return IntentUtils.startActivity(activity, intent);
                }
            } catch (Throwable throwable) {
                return false;
            }
            return true;
        }
        return false;
    }
}

子類:FloatCardDataJump.java

public class FloatCardDataJump extends Jump{
    @Override
    boolean jump(Activity activity, MimoAdInfo adInfo) {
        if (adInfo != null && !TextUtils.isEmpty(adInfo.mFloatCardData)) {
            try {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                final Uri contentUrl = Uri.parse(adInfo.mFloatCardData);
                intent.setData(contentUrl);
                boolean success = IntentUtils.startActivity(activity, intent);
                return success;
            } catch (Exception e) {
                return false;
            }
        }
        return false;
    }
}

客戶端使用程式碼舉例:

/**
     * 點選按鈕區域 先讀取floatcarddata,如果取不到該欄位,再讀取landingpageurl
     * @param adInfo
     */
    public static boolean jumpDownloadByFloatCardDataFirst(MimoAdInfo adInfo) {
        if (adInfo != null && !TextUtils.isEmpty(adInfo.mFloatCardData)) {
            FloatCardDataJump floatCardDataJump = new FloatCardDataJump();
            floatCardDataJump.setNext(new LandingPageJump());
            return floatCardDataJump.start(DkApp.get().getTopActivity(), adInfo);
        } else {
            LandingPageJump landingPageJump = new LandingPageJump();
            return landingPageJump.jump(DkApp.get().getTopActivity(), adInfo);
        }
    }