设计模式 -> 策略模式(Strategy Pattern)

前言

Android开发中,策略模式是一种常用的设计模式,它能够让我们在运行时动态选择算法或行为。本文将重点介绍如何在Android中安全地实现策略模式,避免内存泄漏问题。

传统策略模式的问题

kotlin 复制代码
// ❌ 存在内存泄漏风险的实现
object LazyStart : StartStrategy {
    override operator fun invoke(block: suspend () -> Unit) {
        GlobalScope.launch {
            delay(1000)  
            // 延迟执行可能导致内存泄漏,block表达式持有的Activity/Fragment可能销毁后再执行,导致Activity/Fragment无法被GC
            block()
        }
    }
}

// 危险使用场景
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        LazyStart {
            updateUI()  // Activity可能已销毁,但lambda仍被执行
        }
    }
}

✅ 内存安全的解决方案

方案1:Class实现 + 作用域绑定

kotlin 复制代码
class SafeImmediateStart(private val scope: CoroutineScope) : StartStrategy {
    override operator fun invoke(block: suspend () -> Unit) {
        scope.launch {
            block()
        }
    }
}

class SafeLazyStart(private val scope: CoroutineScope) : StartStrategy {
    override operator fun invoke(block: suspend () -> Unit) {
        scope.launch {
            delay(1000)
            block()
        }
    }
}

// 安全使用
class MainActivity : AppCompatActivity() {
    private val immediateStrategy = SafeImmediateStart(lifecycleScope)
    private val lazyStrategy = SafeLazyStart(lifecycleScope)
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        immediateStrategy {
            updateUI()  // 安全:Activity销毁时协程自动取消
        }
    }
}

方案2:枚举实现 + 作用域绑定

kotlin 复制代码
enum class SafeStartStrategy {
    IMMEDIATE {
        override fun execute(scope: CoroutineScope, block: suspend () -> Unit) {
            scope.launch { block() }
        }
    },
    
    LAZY {
        override fun execute(scope: CoroutineScope, block: suspend () -> Unit) {
            scope.launch {
                delay(1000)
                block()
            }
        }
    };
    
    abstract fun execute(scope: CoroutineScope, block: suspend () -> Unit)
    
    operator fun invoke(scope: CoroutineScope, block: suspend () -> Unit) {
        execute(scope, block)
    }
}

// 使用方式
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        SafeStartStrategy.LAZY(lifecycleScope) {
            updateUI()
        }
    }
}

实际应用场景

kotlin 复制代码
// 内存安全检查清单
class MemorySafeStrategy(
    private val scope: CoroutineScope  // ✅ 1. 绑定正确作用域
) : StartStrategy {
    override operator fun invoke(block: suspend () -> Unit) {
        scope.launch {  // ✅ 2. 使用传入的scope
            try {
                block()
            } catch (e: CancellationException) {
                // ✅ 3. 处理取消异常
                Log.d("Strategy", "Execution cancelled")
            }
        }
    }
}

核心总结

场景 推荐方案 原因
UI操作 Class + lifecycleScope 绑定Activity生命周期
数据处理 Class + viewModelScope 绑定ViewModel生命周期
简单工具 改进枚举 + scope参数 简洁且安全
相关推荐
Alair‎1 小时前
【无标题】
开发语言
Mr.Jessy4 小时前
JavaScript高级:构造函数与原型
开发语言·前端·javascript·学习·ecmascript
云栖梦泽6 小时前
鸿蒙应用签名与上架全流程:从开发完成到用户手中
开发语言·鸿蒙系统
爱上妖精的尾巴7 小时前
6-4 WPS JS宏 不重复随机取值应用
开发语言·前端·javascript
小鸡吃米…8 小时前
Python 列表
开发语言·python
kaikaile19958 小时前
基于C#实现一维码和二维码打印程序
开发语言·c#
我不是程序猿儿9 小时前
【C#】画图控件的FormsPlot中的Refresh功能调用消耗时间不一致缘由
开发语言·c#
rit84324999 小时前
C# Socket 聊天室(含文件传输)
服务器·开发语言·c#
嘉琪0019 小时前
Vue3+JS 高级前端面试题
开发语言·前端·javascript
xunyan62349 小时前
面向对象(下)-接口的理解
java·开发语言