Android 详解:高频使用的 8 种设计模式的核心思想和代码实现

设计模式是解决软件设计问题的经典方案,在 Android 开发中合理使用设计模式能显著提升代码的可维护性、扩展性和可读性。以下是 Android 开发中 ​高频使用的 8 种设计模式,结合实际场景解析其核心思想和代码实现。

一、单例模式(Singleton)

Java实现不同单例模式对应在Kotlin中的实现

核心思想 :确保一个类只有一个实例,并提供全局访问点。
适用场景:全局配置管理、日志工具、数据库客户端等。

kotlin 复制代码
// 双重校验锁单例(线程安全)
class AppConfig private constructor() {
    companion object {
        @Volatile private var instance: AppConfig? = null

        fun getInstance(): AppConfig =
            instance ?: synchronized(this) {
                instance ?: AppConfig().also { instance = it }
            }
    }

    var themeColor: String = "#4CAF50"
}

// 使用
AppConfig.getInstance().themeColor = "#2196F3"

注意事项

  • 避免内存泄漏(单例中不要持有 ActivityView 的引用)。
  • 优先使用依赖注入框架(如 Hilt/Dagger)替代手动单例。

二、观察者模式(Observer)

核心思想 :定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象自动更新。
适用场景:数据与 UI 的绑定、事件总线、实时数据更新。

kotlin 复制代码
// 基于 LiveData 的观察者模式(Android Jetpack)
class UserViewModel : ViewModel() {
    private val _userName = MutableLiveData<String>()
    val userName: LiveData<String> = _userName

    fun updateName(name: String) {
        _userName.value = name
    }
}

// Activity 中观察
userViewModel.userName.observe(this) { name ->
    textView.text = name
}

注意事项

  • 使用 LiveData 替代传统观察者,自动处理生命周期。
  • 避免在观察者回调中执行耗时操作。

三、工厂模式(Factory)

核心思想 :将对象的创建逻辑封装到子类或独立类中,客户端无需关心具体实现。
适用场景:网络请求库的创建、不同数据源的解析器。

kotlin 复制代码
// 抽象工厂模式
interface ImageLoader {
    fun load(url: String)
}

class GlideLoader : ImageLoader {
    override fun load(url: String) { /* Glide 实现 */ }
}

class PicassoLoader : ImageLoader {
    override fun load(url: String) { /* Picasso 实现 */ }
}

object ImageLoaderFactory {
    fun create(type: String): ImageLoader =
        when (type) {
            "glide" -> GlideLoader()
            "picasso" -> PicassoLoader()
            else -> throw IllegalArgumentException("Unknown loader")
        }
}

// 使用
val loader = ImageLoaderFactory.create("glide")
loader.load("https://example.com/image.jpg")

注意事项

  • 结合依赖注入框架,避免工厂类膨胀。
  • 优先使用 @Binds@Provides(Dagger/Hilt)实现工厂逻辑。

四、建造者模式(Builder)

核心思想 :将复杂对象的构造过程拆解为多个步骤,允许灵活组合参数。
适用场景 :配置复杂对象(如 AlertDialog、网络请求配置)。

kotlin 复制代码
class DialogBuilder {
    private var title: String = ""
    private var message: String = ""

    fun setTitle(title: String) = apply { this.title = title }
    fun setMessage(message: String) = apply { this.message = message }

    fun build(): AlertDialog {
        return AlertDialog.Builder(context)
            .setTitle(title)
            .setMessage(message)
            .create()
    }
}

// 使用
val dialog = DialogBuilder()
    .setTitle("提示")
    .setMessage("确认删除吗?")
    .build()
dialog.show()

注意事项

  • Android 中的 AlertDialog 本身已使用建造者模式。
  • 优先使用 Kotlin 的 applyalso 简化链式调用。

五、适配器模式(Adapter)

核心思想 :将一个类的接口转换为客户端期望的另一个接口。
适用场景RecyclerView.Adapter、第三方库接口兼容。

kotlin 复制代码
// RecyclerView 适配器
class UserAdapter(private val users: List<User>) : RecyclerView.Adapter<UserAdapter.ViewHolder>() {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(user: User) {
            itemView.textView.text = user.name
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_user, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(users[position])
    }

    override fun getItemCount() = users.size
}

注意事项

  • 使用 ListAdapterDiffUtil 优化数据更新。
  • 避免在 onBindViewHolder 中执行耗时操作。

六、代理模式(Proxy)

核心思想 :为其他对象提供一个代理以控制对该对象的访问。
适用场景:延迟加载图片、权限检查、网络请求拦截。

kotlin 复制代码
// 图片加载代理(检查缓存)
interface ImageLoader {
    fun load(url: String)
}

class RealImageLoader : ImageLoader {
    override fun load(url: String) { /* 实际加载逻辑 */ }
}

class ImageLoaderProxy : ImageLoader {
    private val realLoader = RealImageLoader()
    private val cache = mutableMapOf<String, Bitmap>()

    override fun load(url: String) {
        if (cache.containsKey(url)) {
            // 显示缓存图片
        } else {
            realLoader.load(url)
            // 将结果存入缓存
        }
    }
}

注意事项

  • Retrofit 和 Glide 等库内部大量使用代理模式。
  • 优先使用 Kotlin 的 by 关键字实现委托。

七、策略模式(Strategy)

核心思想 :定义一系列算法,使其可以相互替换,且算法的变化独立于客户端。
适用场景:支付方式选择、数据加密算法切换。

kotlin 复制代码
interface PaymentStrategy {
    fun pay(amount: Double)
}

class AlipayStrategy : PaymentStrategy {
    override fun pay(amount: Double) { /* 支付宝支付逻辑 */ }
}

class WechatPayStrategy : PaymentStrategy {
    override fun pay(amount: Double) { /* 微信支付逻辑 */ }
}

class PaymentProcessor(private val strategy: PaymentStrategy) {
    fun processPayment(amount: Double) {
        strategy.pay(amount)
    }
}

// 使用
val processor = PaymentProcessor(AlipayStrategy())
processor.processPayment(100.0)

注意事项

  • 结合工厂模式动态创建策略对象。
  • 使用 @Module@Binds(Dagger/Hilt)管理策略依赖。

八、MVVM 模式(Model-View-ViewModel)

核心思想 :分离 UI 逻辑与业务逻辑,通过数据绑定实现响应式 UI。
适用场景:复杂 UI 交互、数据驱动视图更新。

kotlin 复制代码
// ViewModel(业务逻辑)
class UserViewModel : ViewModel() {
    private val _users = MutableLiveData<List<User>>()
    val users: LiveData<List<User>> = _users

    fun loadUsers() {
        viewModelScope.launch {
            _users.value = userRepository.fetchUsers()
        }
    }
}

// Activity/Fragment(视图层)
userViewModel.users.observe(this) { users ->
    adapter.submitList(users)
}

注意事项

  • 使用 DataBindingViewBinding 简化 UI 更新。
  • 通过 LiveDataStateFlow 实现单向数据流。

九、如何选择设计模式?

场景 推荐模式 示例
全局共享配置 单例模式 应用主题、数据库客户端
数据与 UI 同步更新 观察者模式 LiveData 监听、事件总线
动态创建对象 工厂模式 Retrofit 实例化、图片加载器选择
复杂参数配置 建造者模式 AlertDialog 配置、网络请求构建器
接口兼容与转换 适配器模式 RecyclerView 适配器、第三方 SDK 封装
控制对象访问 代理模式 权限检查、缓存代理
算法灵活切换 策略模式 支付方式、数据加密算法
分离 UI 与业务逻辑 MVVM 模式 Jetpack ViewModel + LiveData

十、总结

  1. 避免过度设计:优先使用 Android Jetpack 组件(如 ViewModel、LiveData)内置的模式实现。
  2. 组合使用模式:例如 MVVM + 观察者 + 仓库模式构建稳健架构。
  3. 测试驱动:通过单元测试验证模式实现的正确性和扩展性。
  4. 关注性能:避免在单例或观察者中持有生命周期敏感对象的引用。

更多分享

  1. Android 应用【内存优化】指南
  2. Android 应用【内存泄漏】优化指南
  3. Android ContentProvider 详解及结合 Jetpack Startup 的优化实践
  4. Android 冷启动优化实践:含主线程优化、资源预加载与懒加载、跨进程预热等
  5. Android RecyclerView 性能优化指南
  6. Android 包体积优化实践------入门级攻略
相关推荐
魔芋红茶3 小时前
MySQL 从入门到精通 16:主从复制
android·mysql·adb
2501_915106325 小时前
移动端网页调试实战,iOS WebKit Debug Proxy 的应用与替代方案
android·前端·ios·小程序·uni-app·iphone·webkit
柯南二号6 小时前
【大前端】React Native 调用 Android、iOS 原生能力封装
android·前端·react native
可乐+冰06 小时前
Android 编写高斯模糊功能
android·人工智能·opencv
xzkyd outpaper9 小时前
Android中APK包含哪些内容?
android
蹦极的考拉9 小时前
网站日志里面老是出现{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22.....
android·开发语言·php
安卓开发者10 小时前
Android Glide最佳实践:高效图片加载完全指南
android·glide
菠萝加点糖11 小时前
Android 使用MediaMuxer+MediaCodec编码MP4视频
android·音视频·编码
雨白12 小时前
手写 MaterialEditText:实现浮动标签(Floating Label)效果
android
CYRUS_STUDIO13 小时前
使用 readelf 分析 so 文件:ELF 结构解析全攻略
android·linux·逆向