1. Android开发中的设计模式概述
在Android应用开发过程中,设计模式就像建筑师的蓝图,它们为常见问题提供了经过验证的解决方案。作为一名有五年Android开发经验的工程师,我发现合理运用设计模式可以显著提升代码的可维护性和扩展性。设计模式不是银弹,但掌握它们能让你在面对复杂业务需求时游刃有余。
Android框架本身大量运用了各种设计模式。比如RecyclerView就巧妙结合了适配器模式、观察者模式和组合模式。理解这些模式不仅能帮助你更好地使用Android API,还能在自定义组件时做出更优雅的设计决策。
2. 创建型模式详解与应用
2.1 单例模式的深度实践
单例模式可能是Android开发中最常被滥用的设计模式。正确的单例实现需要考虑线程安全、延迟初始化和反序列化等问题。在Kotlin中,我们可以利用object关键字或by lazy委托来简化实现:
object NetworkManager { private const val TIMEOUT = 30_000 val okHttpClient by lazy { OkHttpClient.Builder() .connectTimeout(TIMEOUT.toLong(), TimeUnit.MILLISECONDS) .build() } }注意:避免在单例中持有Context引用,这可能导致内存泄漏。如果需要Context,使用ApplicationContext。
实际项目中,单例适合用于:
- 全局配置管理
- 日志记录器
- 数据库访问入口
- 网络请求客户端
2.2 工厂模式的变体应用
Android中的BitmapFactory是工厂模式的典型实现。在实际开发中,我们可以扩展基础工厂模式:
interface ViewFactory { fun createView(context: Context): View } class MaterialViewFactory : ViewFactory { override fun createView(context: Context): View { return MaterialButton(context).apply { cornerRadius = resources.getDimension(R.dimen.button_corner) } } } // 使用抽象工厂模式创建系列相关对象 interface UIComponentFactory { fun createButton(): Button fun createTextView(): TextView }工厂模式特别适合:
- 需要统一创建接口的场景
- 对象创建过程复杂的场景
- 需要隔离创建逻辑的场景
2.3 建造者模式的高级用法
Android中的AlertDialog.Builder是建造者模式的典范。我们可以借鉴这种模式创建复杂对象:
class UserProfile private constructor( val name: String, val age: Int, val avatar: Bitmap? ) { class Builder { private var name: String = "" private var age: Int = 0 private var avatar: Bitmap? = null fun setName(name: String) = apply { this.name = name } fun setAge(age: Int) = apply { this.age = age } fun setAvatar(avatar: Bitmap?) = apply { this.avatar = avatar } fun build(): UserProfile { require(name.isNotBlank()) { "Name must not be empty" } require(age > 0) { "Age must be positive" } return UserProfile(name, age, avatar) } } } // 使用示例 val profile = UserProfile.Builder() .setName("John") .setAge(30) .setAvatar(bitmap) .build()建造者模式的优势在于:
- 分步构建复杂对象
- 保证构建过程的正确性
- 提高代码可读性
3. 结构型模式实战解析
3.1 适配器模式的灵活运用
RecyclerView的Adapter是Android中最常见的适配器实现。一个完整的适配器应该处理多种ViewType:
class MultiTypeAdapter( private val items: List<Any> ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { override fun getItemViewType(position: Int): Int { return when(items[position]) { is String -> TYPE_TEXT is Bitmap -> TYPE_IMAGE else -> TYPE_DEFAULT } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when(viewType) { TYPE_TEXT -> TextViewHolder(...) TYPE_IMAGE -> ImageViewHolder(...) else -> DefaultViewHolder(...) } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when(holder) { is TextViewHolder -> holder.bind(items[position] as String) is ImageViewHolder -> holder.bind(items[position] as Bitmap) else -> {} } } }适配器模式的关键点:
- 将接口转换为客户端期望的形式
- 使不兼容的类能够协同工作
- 支持多种数据类型的展示
3.2 代理模式的安全控制
代理模式在Android中常用于权限检查和跨进程通信。下面是一个网络请求代理的实现:
interface ApiService { fun fetchData(): Response } class RealApiService : ApiService { override fun fetchData(): Response { // 实际网络请求实现 } } class ApiServiceProxy( private val realService: ApiService, private val context: Context ) : ApiService { override fun fetchData(): Response { return if (checkNetworkPermission()) { realService.fetchData() } else { throw SecurityException("Network permission required") } } private fun checkNetworkPermission(): Boolean { return ContextCompat.checkSelfPermission( context, Manifest.permission.INTERNET ) == PackageManager.PERMISSION_GRANTED } }代理模式的典型应用场景:
- 远程方法调用(AIDL)
- 虚拟代理(延迟加载)
- 保护代理(权限控制)
- 智能引用(对象生命周期管理)
3.3 组合模式的UI架构
Android的View系统本身就是组合模式的完美体现。我们可以扩展这种模式构建自定义ViewGroup:
class CustomLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : ViewGroup(context, attrs, defStyleAttr) { private val children = mutableListOf<View>() override fun addView(child: View?) { child?.let { children.add(it) super.addView(it) } } override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { var top = paddingTop children.forEach { child -> child.layout( paddingLeft, top, paddingLeft + child.measuredWidth, top + child.measuredHeight ) top += child.measuredHeight + 10 // 10px spacing } } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { var totalHeight = paddingTop + paddingBottom var maxWidth = 0 children.forEach { child -> measureChild(child, widthMeasureSpec, heightMeasureSpec) totalHeight += child.measuredHeight + 10 maxWidth = max(maxWidth, child.measuredWidth) } setMeasuredDimension( resolveSize(maxWidth + paddingLeft + paddingRight, widthMeasureSpec), resolveSize(totalHeight, heightMeasureSpec) ) } }组合模式的核心优势:
- 统一处理简单元素和复杂元素
- 灵活构建对象层次结构
- 简化客户端代码
4. 行为型模式深度剖析
4.1 观察者模式的现代实现
LiveData是Android对观察者模式的现代化改造。我们可以创建自定义的LiveData:
class StockLiveData(private val symbol: String) : LiveData<BigDecimal>() { private val stockManager = StockManager.getInstance() private val listener = { price: BigDecimal -> postValue(price) } override fun onActive() { stockManager.requestPriceUpdates(symbol, listener) } override fun onInactive() { stockManager.removeUpdates(listener) } } // 在ViewModel中使用 class StockViewModel : ViewModel() { private val stockLiveData = StockLiveData("GOOG") fun getStockPrice(): LiveData<BigDecimal> { return stockLiveData } } // 在Activity中观察 viewModel.getStockPrice().observe(this) { price -> priceTextView.text = price.toPlainString() }观察者模式的最佳实践:
- 使用弱引用避免内存泄漏
- 考虑线程安全问题
- 提供取消注册的机制
- 避免在通知过程中修改观察者列表
4.2 策略模式的业务应用
支付策略是策略模式的经典案例。我们可以实现一个更完整的支付系统:
interface PaymentStrategy { fun pay(amount: BigDecimal): PaymentResult val supportedCurrencies: List<Currency> } class AlipayStrategy : PaymentStrategy { override fun pay(amount: BigDecimal): PaymentResult { // 调用支付宝SDK return PaymentResult.Success("Alipay payment successful") } override val supportedCurrencies = listOf(Currency.CNY, Currency.USD) } class PaymentProcessor(private var strategy: PaymentStrategy) { fun processPayment(amount: BigDecimal): PaymentResult { return try { strategy.pay(amount) } catch (e: Exception) { PaymentResult.Failure(e.message ?: "Payment failed") } } fun setStrategy(newStrategy: PaymentStrategy) { strategy = newStrategy } } // 使用示例 val processor = PaymentProcessor(AlipayStrategy()) val result = processor.processPayment(BigDecimal("100.00")) when(result) { is PaymentResult.Success -> showSuccess(result.message) is PaymentResult.Failure -> showError(result.reason) }策略模式的扩展应用:
- 排序算法切换
- 压缩策略选择
- 缓存策略动态调整
- 日志记录策略
4.3 责任链模式的事件处理
Android的事件分发机制就是责任链模式的体现。我们可以实现自己的事件处理器链:
abstract class EventHandler { private var next: EventHandler? = null fun setNext(handler: EventHandler): EventHandler { this.next = handler return handler } fun handle(event: Event): Boolean { return if (canHandle(event)) { doHandle(event) } else { next?.handle(event) ?: false } } protected abstract fun canHandle(event: Event): Boolean protected abstract fun doHandle(event: Event): Boolean } class TouchEventHandler : EventHandler() { override fun canHandle(event: Event) = event is TouchEvent override fun doHandle(event: Event): Boolean { event as TouchEvent // 处理触摸事件 return true } } class KeyEventHandler : EventHandler() { override fun canHandle(event: Event) = event is KeyEvent override fun doHandle(event: Event): Boolean { event as KeyEvent // 处理按键事件 return true } } // 构建责任链 val chain = TouchEventHandler() .setNext(KeyEventHandler()) .setNext(DefaultEventHandler()) // 处理事件 chain.handle(event)责任链模式的适用场景:
- 多级事件处理
- 请求过滤链
- 审批流程
- 异常处理管道
5. Android架构模式演进
5.1 MVC到MVP的转型
传统Android MVC架构的问题在于Activity承担了过多职责。转型MVP的关键步骤:
- 定义View接口:
interface LoginView { fun showLoading() fun hideLoading() fun showError(message: String) fun navigateToHome() }- 实现Presenter:
class LoginPresenter( private val view: LoginView, private val authRepository: AuthRepository ) { fun login(username: String, password: String) { view.showLoading() authRepository.login(username, password) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { view.navigateToHome() }, { error -> view.showError(error.message ?: "Login failed") } ) } }- Activity实现View接口:
class LoginActivity : AppCompatActivity(), LoginView { private lateinit var presenter: LoginPresenter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) presenter = LoginPresenter(this, AuthRepositoryImpl()) loginButton.setOnClickListener { presenter.login( usernameEditText.text.toString(), passwordEditText.text.toString() ) } } override fun showLoading() { progressBar.visibility = View.VISIBLE } // 其他接口方法实现... }MVP的优势:
- 分离视图逻辑和业务逻辑
- 便于单元测试
- 减少Activity代码量
- 提高代码可维护性
5.2 MVVM与数据绑定
MVVM模式结合Data Binding可以极大简化UI代码:
- 定义ViewModel:
class UserViewModel : ViewModel() { private val _user = MutableLiveData<User>() val user: LiveData<User> = _user private val _isLoading = MutableLiveData<Boolean>() val isLoading: LiveData<Boolean> = _isLoading fun loadUser(userId: String) { _isLoading.value = true viewModelScope.launch { try { _user.value = userRepository.getUser(userId) } catch (e: Exception) { // 处理错误 } finally { _isLoading.value = false } } } }- 布局文件使用数据绑定:
<layout> <data> <variable name="viewModel" type="com.example.UserViewModel"/> </data> <LinearLayout> <ProgressBar android:visibility="@{viewModel.isLoading ? View.VISIBLE : View.GONE}"/> <TextView android:text="@{viewModel.user.name}"/> <Button android:onClick="@{() -> viewModel.loadUser("123")}"/> </LinearLayout> </layout>- Activity中绑定ViewModel:
class UserActivity : AppCompatActivity() { private lateinit var binding: ActivityUserBinding private val viewModel by viewModels<UserViewModel>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_user) binding.lifecycleOwner = this binding.viewModel = viewModel } }MVVM的最佳实践:
- 使用LiveData管理状态
- 避免在ViewModel中持有View引用
- 合理使用Data Binding
- 将业务逻辑放在ViewModel中
5.3 MVI架构探索
MVI(Model-View-Intent)是一种新兴的架构模式:
// 状态 data class UserState( val user: User? = null, val isLoading: Boolean = false, val error: String? = null ) // 意图 sealed class UserIntent { object LoadUser : UserIntent() data class Retry(val userId: String) : UserIntent() } class UserViewModel : ViewModel() { private val _state = MutableStateFlow(UserState()) val state: StateFlow<UserState> = _state fun processIntent(intent: UserIntent) { when(intent) { is UserIntent.LoadUser -> loadUser() is UserIntent.Retry -> retry(intent.userId) } } private fun loadUser() { _state.value = _state.value.copy(isLoading = true) viewModelScope.launch { try { val user = userRepository.getUser() _state.value = _state.value.copy( user = user, isLoading = false ) } catch (e: Exception) { _state.value = _state.value.copy( error = e.message, isLoading = false ) } } } }MVI的特点:
- 单向数据流
- 不可变状态
- 明确的意图处理
- 易于调试和测试
6. 设计原则的Android实践
6.1 SOLID原则应用
- 单一职责原则:
// 违反原则的写法 class UserManager { fun login() { /*...*/ } fun saveToDatabase() { /*...*/ } fun uploadAvatar() { /*...*/ } } // 符合原则的写法 class AuthService { fun login() { /*...*/ } } class UserRepository { fun saveToDatabase() { /*...*/ } } class FileUploader { fun uploadAvatar() { /*...*/ } }- 开闭原则示例:
interface DiscountStrategy { fun applyDiscount(price: BigDecimal): BigDecimal } class ChristmasDiscount : DiscountStrategy { override fun applyDiscount(price: BigDecimal) = price * BigDecimal("0.8") } class OrderProcessor(private val discountStrategy: DiscountStrategy) { fun process(order: Order) { val finalPrice = discountStrategy.applyDiscount(order.totalPrice) // 处理订单 } }- 里氏替换原则实践:
open class View(context: Context) { open fun draw(canvas: Canvas) { // 基础绘制逻辑 } } class CustomView(context: Context) : View(context) { override fun draw(canvas: Canvas) { super.draw(canvas) // 自定义绘制逻辑 } }6.2 DRY与KISS原则
避免重复代码的几种方式:
- 使用扩展函数:
fun Context.showToast(message: String, duration: Int = Toast.LENGTH_SHORT) { Toast.makeText(this, message, duration).show() } // 使用 context.showToast("Hello")- 基础工具类:
object DateUtils { private val displayFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) fun formatDate(date: Date): String { return displayFormat.format(date) } }- 合理使用继承:
abstract class BaseActivity : AppCompatActivity() { protected abstract val layoutRes: Int override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(layoutRes) initViews() setupListeners() } protected open fun initViews() {} protected open fun setupListeners() {} }6.3 组合优于继承
Android开发中更推荐使用组合:
class UserProfileView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr) { private val avatarView = ImageView(context).apply { layoutParams = LayoutParams(100, 100) addView(this) } private val nameView = TextView(context).apply { layoutParams = LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT ).apply { topMargin = 8.dp } addView(this) } fun setUser(user: User) { avatarView.loadImage(user.avatarUrl) nameView.text = user.name } }组合的优势:
- 更灵活
- 避免继承层次过深
- 减少耦合
- 便于单元测试
7. 设计模式实战技巧
7.1 模式组合应用
在实际项目中,我们经常组合使用多种设计模式。例如,结合工厂模式和策略模式:
interface NotificationStrategy { fun send(message: String) } class EmailNotification : NotificationStrategy { override fun send(message: String) { // 发送邮件 } } class PushNotification : NotificationStrategy { override fun send(message: String) { // 发送推送 } } object NotificationFactory { fun create(type: NotificationType): NotificationStrategy { return when(type) { NotificationType.EMAIL -> EmailNotification() NotificationType.PUSH -> PushNotification() } } } // 使用 val strategy = NotificationFactory.create(NotificationType.EMAIL) strategy.send("Your order has shipped")7.2 模式选择指南
选择设计模式时考虑以下因素:
- 问题类型:
- 创建对象 → 工厂、建造者、单例
- 对象结构 → 适配器、代理、装饰器
- 对象行为 → 观察者、策略、命令
- 变化维度:
- 识别哪些部分可能变化
- 将变化部分封装起来
- 复杂度评估:
- 简单问题不需要复杂模式
- 过度设计会增加维护成本
7.3 常见反模式识别
- 单例滥用:
- 导致紧耦合
- 难以测试
- 可能引起内存泄漏
- 过度继承:
- 类层次过深
- 脆弱的基类问题
- 难以扩展
- 上帝对象:
- 一个类做太多事情
- 难以维护
- 违反单一职责原则
- 过早优化:
- 使用复杂模式解决简单问题
- 增加不必要的抽象层
- 降低代码可读性
8. 性能优化与设计模式
8.1 对象池模式
对象池模式可以优化频繁创建销毁对象的场景:
class BitmapPool(private val maxSize: Int) { private val pool = Stack<Bitmap>() fun getBitmap(): Bitmap { return if (pool.isEmpty()) { createBitmap() } else { pool.pop().apply { eraseColor(Color.TRANSPARENT) } } } fun recycle(bitmap: Bitmap) { if (pool.size < maxSize) { pool.push(bitmap) } else { bitmap.recycle() } } private fun createBitmap(): Bitmap { return Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) } }对象池适用场景:
- 频繁创建销毁的对象
- 初始化成本高的对象
- 内存敏感的环境
8.2 享元模式优化
Android中的Typeface就是享元模式的实现。我们可以创建自己的享元工厂:
object IconFactory { private val iconCache = mutableMapOf<String, Drawable>() fun getIcon(resId: Int, tint: Int? = null): Drawable { val key = "$resId${tint ?: ""}" return iconCache.getOrPut(key) { val drawable = ContextCompat.getDrawable(context, resId)!! tint?.let { drawable.setTint(it) } drawable } } }享元模式的关键点:
- 共享细粒度对象
- 分离内部状态和外部状态
- 使用工厂控制创建
8.3 懒加载策略
结合代理模式实现智能懒加载:
class SmartImageLoader(private val context: Context) { private val memoryCache = LruCache<String, Bitmap>(maxMemory / 8) private val diskCache = DiskLruCache(context.cacheDir, 10 * 1024 * 1024) fun load(url: String, imageView: ImageView) { val cached = memoryCache.get(url) if (cached != null) { imageView.setImageBitmap(cached) return } imageView.tag = url CoroutineScope(Dispatchers.IO).launch { val bitmap = diskCache.get(url) ?: download(url) withContext(Dispatchers.Main) { if (imageView.tag == url) { imageView.setImageBitmap(bitmap) } memoryCache.put(url, bitmap) } } } }懒加载的最佳实践:
- 多级缓存策略
- 避免内存泄漏
- 考虑线程安全
- 提供取消机制
9. 测试与设计模式
9.1 依赖注入与测试
依赖注入(DI)可以极大提高代码的可测试性:
interface UserRepository { fun getUser(id: String): User } class UserViewModel( private val userRepository: UserRepository, private val dispatcher: CoroutineDispatcher = Dispatchers.Main ) : ViewModel() { // ... } // 测试 class TestUserRepository : UserRepository { override fun getUser(id: String): User { return User("test", "Test User") } } @Test fun testUserViewModel() { val testDispatcher = TestCoroutineDispatcher() val viewModel = UserViewModel(TestUserRepository(), testDispatcher) // 测试逻辑 }依赖注入的优势:
- 松耦合
- 易于模拟依赖
- 可配置性强
- 便于单元测试
9.2 模拟对象策略
使用策略模式实现可测试的组件:
interface Clock { fun currentTime(): Long } class SystemClock : Clock { override fun currentTime() = System.currentTimeMillis() } class TestClock(private val fixedTime: Long) : Clock { override fun currentTime() = fixedTime } class TimeDisplay(private val clock: Clock) { fun displayTime(): String { return SimpleDateFormat("HH:mm:ss", Locale.getDefault()) .format(Date(clock.currentTime())) } } // 测试 @Test fun testTimeDisplay() { val fixedTime = 1625097600000L // 2021-06-30 00:00:00 val display = TimeDisplay(TestClock(fixedTime)) assertEquals("00:00:00", display.displayTime()) }9.3 测试观察者模式
测试LiveData或RxJava等观察者实现:
@Test fun testLiveDataObserver() { val liveData = MutableLiveData<String>() val testObserver = TestObserver<String>() liveData.observeForever(testObserver) liveData.value = "first" liveData.value = "second" assertEquals(2, testObserver.valueCount) assertEquals("first", testObserver.values[0]) assertEquals("second", testObserver.values[1]) liveData.removeObserver(testObserver) } class TestObserver<T> : Observer<T> { val values = mutableListOf<T>() var valueCount = 0 override fun onChanged(value: T) { values.add(value) valueCount++ } }测试观察者的要点:
- 验证通知次数
- 验证通知顺序
- 验证通知内容
- 测试取消注册
10. Kotlin特性与设计模式
10.1 对象声明实现单例
Kotlin的object关键字简化了单例实现:
object NetworkManager { private const val TIMEOUT = 30_000 val okHttpClient by lazy { OkHttpClient.Builder() .connectTimeout(TIMEOUT.toLong(), TimeUnit.MILLISECONDS) .build() } }注意:Kotlin对象声明是线程安全的,但内部属性仍需考虑线程安全。
10.2 扩展函数实现装饰器
使用扩展函数实现装饰器模式:
fun RecyclerView.addDivider( divider: Drawable = DividerItemDecoration.DEFAULT_DRAWABLE, orientation: Int = DividerItemDecoration.VERTICAL ) { addItemDecoration(DividerItemDecoration(context, orientation).apply { divider.let { setDrawable(it) } }) } // 使用 recyclerView.addDivider()扩展函数的优势:
- 不修改原有类
- 语法简洁
- 可读性强
- 减少辅助类
10.3 高阶函数实现策略
Kotlin的高阶函数可以替代策略接口:
fun calculatePrice( originalPrice: BigDecimal, discountStrategy: (BigDecimal) -> BigDecimal ): BigDecimal { return discountStrategy(originalPrice) } // 使用 val finalPrice = calculatePrice(BigDecimal("100")) { price -> price * BigDecimal("0.9") // 打九折 }高阶函数的特点:
- 减少接口定义
- 更灵活的策略组合
- 支持lambda表达式
- 与Kotlin标准库良好集成
10.4 密封类实现状态模式
使用密封类优雅地实现状态模式:
sealed class DownloadState { object Idle : DownloadState() data class Progress(val percent: Int) : DownloadState() data class Success(val file: File) : DownloadState() data class Error(val exception: Throwable) : DownloadState() } class DownloadManager { private var currentState: DownloadState = DownloadState.Idle fun updateState(newState: DownloadState) { currentState = newState when(newState) { is DownloadState.Idle -> cancelDownloads() is DownloadState.Progress -> updateProgress(newState.percent) is DownloadState.Success -> notifyDownloadComplete(newState.file) is DownloadState.Error -> showError(newState.exception) } } }密封类的优势:
- 完备的状态集合
- 清晰的模式匹配
- 编译时检查
- 减少错误处理
11. 设计模式在Jetpack组件中的应用
11.1 ViewModel与生命周期感知
ViewModel是Android架构组件对设计模式的创新应用:
class UserViewModel( private val savedStateHandle: SavedStateHandle, private val userRepository: UserRepository ) : ViewModel() { private val _user = savedStateHandle.getLiveData<User>("user") val user: LiveData<User> = _user init { viewModelScope.launch { try { _user.value = userRepository.getUser() } catch (e: Exception) { // 处理错误 } } } fun updateUserName(name: String) { _user.value = _user.value?.copy(name = name) } override fun onCleared() { // 清理资源 super.onCleared() } }ViewModel的设计特点:
- 生命周期感知
- 数据持久化
- 协程集成
- 与UI解耦
11.2 Room数据库的DAO模式
Room数据库使用DAO(Data Access Object)模式:
@Dao interface UserDao { @Insert suspend fun insert(user: User) @Update suspend fun update(user: User) @Query("SELECT * FROM user WHERE id = :userId") suspend fun getUser(userId: String): User? @Query("DELETE FROM user WHERE id = :userId") suspend fun delete(userId: String) } @Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao } // 使用 val db = Room.databaseBuilder( context, AppDatabase::class.java, "app-db" ).build() val userDao = db.userDao() viewModelScope.launch { userDao.insert(User("1", "John")) }DAO模式的优势:
- 统一数据访问接口
- 分离业务逻辑与数据访问
- 便于替换数据源
- 提高可测试性
11.3 WorkManager的任务调度
WorkManager使用命令模式封装后台任务:
class UploadWorker( context: Context, workerParams: WorkerParameters ) : CoroutineWorker(context, workerParams) { override suspend fun doWork(): Result { val fileUri = inputData.getString("file_uri") ?: return Result.failure() return try { uploadFile(fileUri) Result.success() } catch (e: Exception) { if (runAttemptCount < MAX_RETRY) { Result.retry() } else { Result.failure() } } } private suspend fun uploadFile(uri: String) { // 上传逻辑 } } // 调度工作 val uploadWork = OneTimeWorkRequestBuilder<UploadWorker>() .setInputData(workDataOf("file_uri" to fileUri.toString())) .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build() ) .build() WorkManager.getInstance(context).enqueue(uploadWork)命令模式的特点:
- 封装请求为对象
- 支持排队和执行
- 支持撤销和重做
- 支持日志和事务
12. 设计模式在第三方库中的应用
12.1 Retrofit的代理模式
Retrofit使用动态代理创建API接口:
interface GitHubService { @GET("users/{user}/repos") suspend fun listRepos(@Path("user") user: String): List<Repo> } val retrofit = Retrofit.Builder() .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build() val service = retrofit.create(GitHubService::class.java) // 使用 viewModelScope.launch { try { val repos = service.listRepos("octocat") // 处理结果 } catch (e: Exception) { // 处理错误 } }动态代理的优势:
- 减少样板代码
- 灵活处理请求和响应
- 支持多种转换器
- 易于扩展
12.2 Glide的装饰器模式
Glide使用装饰器模式扩展图片加载功能:
Glide.with(context) .load(url) .placeholder(R.drawable.placeholder) .error(R.drawable.error) .transform(CircleCrop(), GrayscaleTransformation()) .into(imageView)装饰器模式的特点:
- 动态添加功能
- 避免子类爆炸
- 保持单一职责
- 灵活组合功能
12.3 Dagger的依赖注入
Dagger实现依赖注入模式:
@Module class NetworkModule { @Provides fun provideOkHttpClient(): OkHttpClient { return OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .build() } @Provides fun provideRetrofit(client: OkHttpClient): Retrofit { return Retrofit.Builder() .baseUrl("https://api.example.com/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() } } @Component(modules = [NetworkModule::class]) interface ApplicationComponent { fun inject(activity: MainActivity) } // 使用 class MainActivity : AppCompatActivity() { @Inject lateinit var retrofit: Retrofit override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (application as MyApp).component.inject(this) } }依赖注入的优势:
- 松耦合
- 可测试性强
- 集中配置
- 生命周期管理
13. 设计模式在自定义View中的应用
13.1 组合模式构建复杂View
自定义ViewGroup使用组合模式:
class TagLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : ViewGroup(context, attrs, defStyleAttr) { private val horizontalSpacing = 8.dp private val verticalSpacing = 4.dp override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { var totalHeight = 0 var currentLineWidth = 0 var currentLineHeight = 0 for (i in 0 until childCount) { val child = getChildAt(i) measureChild(child, widthMeasureSpec, heightMeasureSpec) val childWidth = child.measuredWidth val childHeight = child.measuredHeight if (currentLineWidth + childWidth > measuredWidth) { totalHeight += currentLineHeight +