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

501 阅读5分钟

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

一、单例模式(Singleton)

Java实现不同单例模式对应在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"

注意事项

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

二、观察者模式(Observer)

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

// 基于 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)

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

// 抽象工厂模式
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、网络请求配置)。

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 的 apply 和 also 简化链式调用。

五、适配器模式(Adapter)

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

// 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
}

注意事项

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

六、代理模式(Proxy)

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

// 图片加载代理(检查缓存)
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)

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

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 交互、数据驱动视图更新。

// 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)
}

注意事项

  • 使用 DataBinding 或 ViewBinding 简化 UI 更新。
  • 通过 LiveData 和 StateFlow 实现单向数据流。

九、如何选择设计模式?

场景推荐模式示例
全局共享配置单例模式应用主题、数据库客户端
数据与 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 包体积优化实践——入门级攻略