Kotlin封装多第三方接口:简化实现,避免冗余样板代码
简化第三方服务封装的Kotlin实现方案
针对你遇到的重复编写服务判断逻辑的问题,这里提供几种Kotlin特有的简化方案,核心思路是利用类委托和动态代理减少样板代码。
方案一:类委托+适配器(推荐,无反射依赖)
这种方式通过定义通用接口+适配器,把两个第三方服务适配到同一通用接口,再用Kotlin的类委托自动实现通用方法,彻底避免重复的null判断。
步骤1:定义通用函数接口
先把两个第三方接口的通用函数抽成独立接口:
// 包含所有通用函数的接口 interface Common3rdPartyService { fun fun1(): Int? fun fun2() // ... 其他约10个通用函数 }
步骤2:编写适配器类
用Kotlin的类委托特性,快速实现通用接口的适配,无需手动重写每个方法:
// 适配I3rdParty1到通用接口 class Service1Adapter(private val service: I3rdParty1) : Common3rdPartyService by service // 适配I3rdParty2到通用接口 class Service2Adapter(private val service: I3rdParty2) : Common3rdPartyService by service
步骤3:实现统一服务类
定义统一接口,然后在实现类中仅处理独有函数,通用函数直接委托给适配器:
// 统一接口:通用函数+两个服务的独有函数 interface MyService : Common3rdPartyService, I3rdParty1, I3rdParty2 class MyCode : MyService { private var commonService: Common3rdPartyService? = null private var service1: I3rdParty1? = null private var service2: I3rdParty2? = null fun detectService() { val serviceProvider = Service() service1 = serviceProvider.getService1() service2 = serviceProvider.getService2() // 确定可用的通用服务适配器 commonService = service1?.let { Service1Adapter(it) } ?: service2?.let { Service2Adapter(it) } } // 通用函数直接转发给适配器,无需重复判断 override fun fun1(): Int? = commonService?.fun1() override fun fun2() = commonService?.fun2() // ... 其他通用函数同理,一行搞定 // 独有函数直接调用对应服务实例(因为只有一个服务可用,不会出现空指针) override fun funA() = service1?.funA() override fun funB() = service1?.funB() // ... I3rdParty1的其他独有函数 override fun funX() = service2?.funX() override fun funY() = service2?.funY() // ... I3rdParty2的其他独有函数 }
方案二:动态代理(无样板代码,但需反射依赖)
如果不想手动定义通用接口和适配器,可以用Java的动态代理机制,自动将所有方法调用转发到可用的服务实例。需要引入kotlin-reflect依赖。
实现代码
import java.lang.reflect.Proxy fun createMyService(): MyService { val serviceProvider = Service() val service1 = serviceProvider.getService1() val service2 = serviceProvider.getService2() // 确定唯一可用的服务实例 val availableService = service1 ?: service2 ?: throw IllegalStateException("No valid service available") return Proxy.newProxyInstance( MyService::class.java.classLoader, arrayOf(MyService::class.java) ) { _, method, args -> try { // 优先调用可用服务的方法 method.invoke(availableService, *args.orEmpty()) } catch (e: NoSuchMethodException) { // 若当前服务没有该方法(即另一个服务的独有函数),返回null或空实现 null } } as MyService } // 统一接口无需修改 interface MyService : I3rdParty1, I3rdParty2
使用时直接调用createMyService()获取实例,所有方法调用都会自动转发到可用服务,完全不用手动实现任何方法。
方案三:通用调用函数(轻量简化)
如果不想引入适配器或反射,可以定义一个通用的调用函数,封装重复的null判断逻辑:
class MyCode : MyService { private var service1: I3rdParty1? = null private var service2: I3rdParty2? = null fun detectService() { val serviceProvider = Service() service1 = serviceProvider.getService1() service2 = serviceProvider.getService2() } // 通用调用逻辑封装 private inline fun <T> invokeCommon(crossinline block1: (I3rdParty1) -> T, crossinline block2: (I3rdParty2) -> T): T? { return service1?.let(block1) ?: service2?.let(block2) } // 无返回值的通用函数 private inline fun invokeCommonUnit(crossinline block1: (I3rdParty1) -> Unit, crossinline block2: (I3rdParty2) -> Unit) { service1?.let(block1) ?: service2?.let(block2) } // 通用函数只需一行调用 override fun fun1(): Int? = invokeCommon({ it.fun1() }, { it.fun1() }) override fun fun2() = invokeCommonUnit({ it.fun2() }, { it.fun2() }) // ... 其他通用函数同理 // 独有函数直接调用对应服务 override fun funA() = service1?.funA() override fun funX() = service2?.funX() }
这种方式把重复的判断逻辑封装到两个通用函数中,每个接口方法只需一行代码完成转发。
内容的提问来源于stack exchange,提问作者babygabe2022
相关产品推荐
相关产品推荐

