利用责任链模式,设计一款启动时可以依次弹出的dialog

664 阅读3分钟

一、Okhttp的责任链模式

先看一下,OkHttp 的责任链模式主要通过 Interceptor 接口和 RealInterceptorChain 类实现。下面是一些关键代码片段,展示了其实现方式。

1. Interceptor 接口

java
复制代码
public interface Interceptor {
    Response intercept(Chain chain) throws IOException;

    interface Chain {
        Request request();
        Response proceed(Request request) throws IOException;
        // Other methods
    }
}

2. RealInterceptorChain 类

java
复制代码
public final class RealInterceptorChain implements Interceptor.Chain {
    private final List<Interceptor> interceptors;
    private final int index;
    private final Request request;

    public RealInterceptorChain(List<Interceptor> interceptors, int index, Request request) {
        this.interceptors = interceptors;
        this.index = index;
        this.request = request;
    }

    @Override
    public Request request() {
        return request;
    }

    @Override
    public Response proceed(Request request) throws IOException {
        if (index >= interceptors.size()) throw new AssertionError();

        RealInterceptorChain next = new RealInterceptorChain(interceptors, index + 1, request);
        Interceptor interceptor = interceptors.get(index);
        Response response = interceptor.intercept(next);
        return response;
    }
}

3. OkHttpClient 类

java
复制代码
public class OkHttpClient {
    private final List<Interceptor> interceptors;

    public OkHttpClient() {
        this.interceptors = new ArrayList<>();
        // Add default interceptors if necessary
    }

    public Response newCall(Request request) throws IOException {
        RealInterceptorChain chain = new RealInterceptorChain(interceptors, 0, request);
        return chain.proceed(request);
    }
}

4. Interceptor 实现示例

java
复制代码
public class LoggingInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        long t1 = System.nanoTime();
        System.out.println(String.format("Sending request %s on %s%n%s",
            request.url(), chain.connection(), request.headers()));

        Response response = chain.proceed(request);

        long t2 = System.nanoTime();
        System.out.println(String.format("Received response for %s in %.1fms%n%s",
            response.request().url(), (t2 - t1) / 1e6d, response.headers()));

        return response;
    }
}

概述

  1. Interceptor 接口定义了处理请求和响应的方法。
  2. RealInterceptorChain负责依次调用链中的每个 Interceptor
  3. OkHttpClient管理 Interceptor 列表并启动请求链。
  4. Interceptor 的实现通过实现 intercept 方法处理具体的逻辑。

这种设计使得请求和响应可以通过一系列可配置的拦截器进行处理,确保了代码的灵活性和可扩展性。

二、弹框处理器

我们可以用类似的方式来实现我们的弹框处理器链。

重新设计的弹框处理器责任链

1. 定义 Interceptor 接口

每个弹框处理器都需要实现 Interceptor 接口,该接口包含一个 intercept 方法,负责处理弹框逻辑。

kotlin
复制代码
package com.example.popupchain

interface Interceptor {
    fun intercept(chain: InterceptorChain)
}

2. 定义 InterceptorChain 类

InterceptorChain 负责管理拦截器链,并依次调用每个拦截器的 intercept 方法。

kotlin
复制代码
package com.example.popupchain

import android.content.Context

class InterceptorChain(
    private val interceptors: List<Interceptor>,
    private val index: Int,
    private val context: Context
) {
    fun proceed() {
        if (index < interceptors.size) {
            val nextChain = InterceptorChain(interceptors, index + 1, context)
            val interceptor = interceptors[index]
            interceptor.intercept(nextChain)
        }
    }
}

3. 实现具体的弹框拦截器

每个弹框拦截器实现 Interceptor 接口,并在处理完弹框逻辑后调用 proceed 方法继续链中的下一个拦截器。

WelcomePopupInterceptor.kt
kotlin
复制代码
package com.example.popupchain.interceptors

import android.app.AlertDialog
import com.example.popupchain.Interceptor
import com.example.popupchain.InterceptorChain

class WelcomePopupInterceptor : Interceptor {
    override fun intercept(chain: InterceptorChain) {
        val context = chain.context
        val dialog = AlertDialog.Builder(context)
            .setTitle("Welcome")
            .setMessage("Welcome to our app!")
            .setPositiveButton("OK") { _, _ ->
                chain.proceed()
            }
            .create()

        dialog.show()
    }
}
UpdatePopupInterceptor.kt
kotlin
复制代码
package com.example.popupchain.interceptors

import android.app.AlertDialog
import com.example.popupchain.Interceptor
import com.example.popupchain.InterceptorChain

class UpdatePopupInterceptor : Interceptor {
    override fun intercept(chain: InterceptorChain) {
        val context = chain.context
        val dialog = AlertDialog.Builder(context)
            .setTitle("Update")
            .setMessage("A new update is available.")
            .setPositiveButton("Update") { _, _ ->
                chain.proceed()
            }
            .setNegativeButton("Later") { _, _ ->
                chain.proceed()
            }
            .create()

        dialog.show()
    }
}
TipsPopupInterceptor.kt
kotlin
复制代码
package com.example.popupchain.interceptors

import android.app.AlertDialog
import com.example.popupchain.Interceptor
import com.example.popupchain.InterceptorChain

class TipsPopupInterceptor : Interceptor {
    override fun intercept(chain: InterceptorChain) {
        val context = chain.context
        val dialog = AlertDialog.Builder(context)
            .setTitle("Tip")
            .setMessage("Did you know you can do X, Y, Z?")
            .setPositiveButton("Got it") { _, _ ->
                chain.proceed()
            }
            .create()

        dialog.show()
    }
}

4. 创建 PopupChainManager

PopupChainManager 负责管理拦截器链,并启动链式调用。

kotlin
复制代码
package com.example.popupchain

import com.example.popupchain.interceptors.WelcomePopupInterceptor
import com.example.popupchain.interceptors.UpdatePopupInterceptor
import com.example.popupchain.interceptors.TipsPopupInterceptor

object PopupChainManager {
    private val interceptors = listOf(
        WelcomePopupInterceptor(),
        UpdatePopupInterceptor(),
        TipsPopupInterceptor()
    )

    fun handlePopups(context: Context) {
        val chain = InterceptorChain(interceptors, 0, context)
        chain.proceed()
    }
}

5. 在 MainActivity 中调用 PopupChainManager

kotlin
复制代码
package com.example.popupchain

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 调用 PopupChainManager 开始处理弹框
        PopupChainManager.handlePopups(this)
    }
}

总结

通过参考 OkHttp 的责任链实现,我们将弹框处理器的设计进行了优化,使其更加优雅和灵活。每个弹框处理器作为一个 Interceptor,通过 InterceptorChain 进行串联和调用,简化了弹框处理的逻辑,并且方便扩展新的弹框处理器。希望这篇文章的示例能帮助你在项目中实现类似的功能。