重学设计模式之拦截器和责任链

拦截的含义

在软件设计中,"拦截"指的是在某个执行流程中插入一个或多个处理点,这些处理点可以检查、修改或者替换原有流程中的数据或行为。拦截器可以在不修改原有代码的情况下,对特定的操作进行增强或改变。

拦截器的核心思想

拦截器模式(Interceptor Pattern)是一种设计模式,它允许你在调用某个方法之前或之后,插入额外的处理逻辑。这些逻辑可以是日志记录、性能监控、安全控制等。

拦截器的工作方式

通常,拦截器会定义一个接口,该接口包含了一个方法(如intercept),该方法接收一个"调用对象"。该拦截器可以在调用原始操作之前和之后执行自己的逻辑,甚至可以决定是否调用原始操作。

拦截器与责任链的关系

拦截器通常组织成责任链,每个拦截器在链中依次被调用。每个拦截器都可以决定是否将请求传递给下一个责任链,或者直接返回相应,从而中断链。

在责任链中,拦截器可以对请求进行拦截,即在请求到达目标之前进行预处理,也可以在响应返回之后进行处理。这里的拦截并不是完成阻断,而是类似于"中间处理"的意思。

责任链模式在拦截器中的核心体现

链式传递机制

  • 每个拦截器接收一个Chain对象
  • 通过调用chain.proceed()将控制权传递给下一个拦截器
  • 形成了明确的"传递链"

灵活的组织结构

  • 拦截器可以动态添加、移除、排序
  • 每个拦截器不需要知道链中的其他拦截器
  • 符合"开闭原则"(对扩展开放,对修改封闭)

统一处理接口

  • 所有拦截器实现相同的接口
  • 链的节点有统一的处理方式

流程控制

  • 拦截器可以选择是否继续传递(调用proceed())
  • 可以修改拦截前和拦截后的逻辑

总结

责任链模式让多个拦截器能够有序地、灵活地组合在一起,形成一个处理流水线,每个拦截器都是这个流水线上的一个工作站,而chain对象就是传送带,负责在站与站之间传递工作项。

示例代码

定义责任链接口Chain

kotlin 复制代码
//责任链接口
interface Chain {
    fun request():Request
    fun proceed(request: Request):Response
}

拦截器接口Interceptor

kotlin 复制代码
//拦截器接口
interface Interceptor {
    fun interceptor(chain:Chain):Response
}

请求对象

kotlin 复制代码
//请求对象
data class Request(val userName:String,val passWord:String,val headers:Map<String,String> = HashMap())

响应对象

kotlin 复制代码
//响应对象
data class Response(val code:Int,val message:String,val token:String? = null)

日志拦截器

kotlin 复制代码
class LoggingInterceptor: Interceptor {
    override fun interceptor(chain: Chain): Response {
        val request = chain.request()
        println("📝 [日志] 收到登录请求: ${request.userName}")

        // 继续执行下一个拦截器或真实请求
        val response = chain.proceed(request)

        println("📝 [日志] 返回结果: ${response.message} (code=${response.code})")
        return response
    }
}

校验拦截器

kotlin 复制代码
class ValidationInterceptor:Interceptor {
    override fun interceptor(chain: Chain): Response {
        val request = chain.request()
        if(request.userName==""){
            return Response(400,"用户名不为空")
        }
        if(request.passWord.length<6){
            return Response(400,"密码长度不能少于6位")
        }
        println("校验通过")
        //校验通过,继续
        return chain.proceed(request)
    }
}

认证拦截器

kotlin 复制代码
class AuthInterceptor : Interceptor {
    override fun interceptor(chain: Chain): Response {
        val original = chain.request()
        val newRequest = original.copy(
                headers = original.headers + mapOf("Device-ID" to "DEVICE_8888")
        )
        println("🔑 [认证] 添加设备ID到请求头")
        val reponse = chain.proceed(newRequest)
        println("认证返回结果")
        return  reponse
    }
}

核心代码

kotlin 复制代码
class RealChain(
        private val interceptors:List<Interceptor>,
        private val index:Int,
        private val originalRequest:Request
):Chain {

    override fun request(): Request {
        return originalRequest
    }

    override fun proceed(request: Request): Response {
        //所有拦截器执行完毕,执行真实业务
        if(index >= interceptors.size){
            return executeRealLogin(request)
        }
        //获取当前拦截器,并创建下一个chain
        val nextChain = RealChain(interceptors,index+1,request)
        return interceptors[index].interceptor(nextChain)
    }


    private fun executeRealLogin(request: Request):Response{

        println("✅ 执行真实登录: ${request.userName}")
        return if (request.userName == "admin" && request.passWord == "123456") {
            Response(200, "登录成功", "abc123xyz")
        } else {
            Response(401, "用户名或密码错误")
        }
    }

}

日志输出

使用拦截器+责任链之后:

职责分离:每个拦截器只做一件事(单一职责)

可插拔扩展:新增功能只需要加一个Interceptor,无需改主流程

短路机制:当某个拦截器判断"无需继续时",可直接返回Response,不再调用chain.proceed()

java 复制代码
if (isCached) {
    return cacheResponse; // 不再往下传
}
return chain.proceed(request); // 继续传递

比如以下场景:

  • 缓存命中 → 直接返回,跳过网络请求
  • Token 过期 → 返回错误,不执行后续业务
  • 权限不足 → 拦截并返回 403

这是责任链模式的特性:处理者可自主决定是否将请求传递给下一个节点。

比如在项目中,比如有免密支付和创建预订单两个拦截器去构建请求request。

我需要先进行请求免费支付流程,如果是PayPal才会走免密支付,否则直接return success,交由下一个拦截器创建预订单流程。

如果是免密支付则会赋值freePwd=true并传递给创建预订单的接口,预订单接口请求成功后结束拦截器流程(因为就两个拦截器),比如请求google支付的话就需要将请求预订单成功拿到返回的订单id(obfuscatedProfile)传递给google

sdk拉起支付。

代码示例:

支付拦截器流程分析

拦截器1:有密支付拦截器

检查是否满足有密支付条件(如用户开通了该功能)

若满足:执行有密支付逻辑,成功后设置 bypassPayment = true

若不满足:直接调用 chain.proceed() 继续下一个拦截器

拦截器2:创建预订单拦截器

检查 bypassPayment 标志

若为 true:直接使用有密支付结果

若为 false:创建新预订单

对 Google Pay 等渠道处理支付参数(如获取 obfuscatedProfile)

终止条件

当预订单创建完成后,责任链结束

代码实现示例(Kotlin)

kotlin 复制代码
// 支付请求类(贯穿整个责任链)
data class PaymentRequest(
    val isFastPayEnabled: Boolean,
    var isBypassPayment: Boolean = false,
    var paymentToken: String? = null,
    var orderId: String? = null
)

// 支付响应类
data class PaymentResponse(
    val isSuccess: Boolean,
    val orderId: String? = null,
    val error: String? = null
)

// 拦截器接口
interface PaymentInterceptor {
    fun intercept(chain: PaymentChain): PaymentResponse
}

// 责任链接口
interface PaymentChain {
    val request: PaymentRequest
    fun proceed(): PaymentResponse
}

// 有密支付拦截器
class FastPayInterceptor : PaymentInterceptor {
    override fun intercept(chain: PaymentChain): PaymentResponse {
        val req = chain.request
        
        if (!req.isFastPayEnabled) {
            return chain.proceed() // 继续下一个拦截器
        }

        return simulateFastPay().also {
            if (it.isSuccess) {
                req.isBypassPayment = true
                req.paymentToken = "FAST_${System.currentTimeMillis()}"
            }
        } ?: chain.proceed()
    }

    private fun simulateFastPay(): PaymentResponse {
        println("⚡ 执行有密支付...")
        return PaymentResponse(true) // 模拟成功
    }
}

// 预订单拦截器
class OrderInterceptor : PaymentInterceptor {
    override fun intercept(chain: PaymentChain): PaymentResponse {
        val req = chain.request
        
        return when {
            else -> {
                val order = createOrder()
                if (order.isSuccess) {
                    req.orderId = "ORDER_${System.currentTimeMillis()}"
                    println("🛒 创建预订单: ${req.orderId}")
                    processGooglePay(order)
                }
                order
            }
        }
    }

    private fun createOrder(): PaymentResponse {
        println("⏳ 创建预订单...")
        return PaymentResponse(true)
    }

    private fun processGooglePay(order: PaymentResponse) {
        if (order.isSuccess) {
            println(" 处理Google Pay,获取obfuscatedProfile...")
            // 这里会返回给客户端用于调起Google Pay SDK
        }
    }
}

// 实现的责任链
class RealPaymentChain(
    override val request: PaymentRequest,
    private val interceptors: List<PaymentInterceptor>,
    private val index: Int = 0
) : PaymentChain {
    override fun proceed(): PaymentResponse {
        return if (index < interceptors.size) {
            interceptors[index].intercept(
                RealPaymentChain(request, interceptors, index + 1)
            )
        } else {
            // 所有拦截器执行完毕的默认响应
            PaymentResponse(false, error = "支付流程未完成")
        }
    }
}

// 客户端调用
fun main() {
    val request = PaymentRequest(isFastPayEnabled = true) // 测试有密支付
    // val request = PaymentRequest(isFastPayEnabled = false) // 测试普通支付
    
    val chain = RealPaymentChain(
        request,
        listOf(FastPayInterceptor(), OrderInterceptor())
    )
    
    val response = chain.proceed()
    println("\n💳 最终结果: $response")
}

状态传递:通过共享的 PaymentRequest 对象在拦截器间传递状态,最终构建一个request。

相关推荐
小码过河.2 小时前
设计模式——享元模式
java·设计模式·享元模式
Geoking.16 小时前
【设计模式】中介者模式(Mediator)详解
java·设计模式·中介者模式
Yuzhiyuxia18 小时前
【设计模式】设计模式学习总结
学习·设计模式
小屁猪qAq19 小时前
设计模式的基石
开发语言·c++·设计模式
一条闲鱼_mytube19 小时前
智能体设计模式(一):提示链、路由与并行化
人工智能·设计模式
Yu_Lijing21 小时前
基于C++的《Head First设计模式》笔记——模版方法模式
笔记·设计模式
Yu_Lijing1 天前
基于C++的《Head First设计模式》笔记——外观模式
c++·笔记·设计模式
老蒋每日coding1 天前
AI智能体设计模式系列(六)—— 规划模式
人工智能·设计模式
IT永勇1 天前
c++设计模式-观察者模式
c++·观察者模式·设计模式