Android 常用设计模式速查

Android 常用设计模式速查

本文整理 Android 开发中常见技术点对应的设计模式,并给出简化伪代码、典型源码/原理使用位置。伪代码用于理解模式结构,不等同于源码实现。

总览

设计模式 Android 常见技术点 典型使用位置
单例模式 全局管理器、系统服务、数据库实例 WorkManager.getInstance()Room.databaseBuilder() 后的数据库单例、SystemServiceRegistry
Builder 模式 复杂对象构建 AlertDialog.BuilderNotificationCompat.BuilderRoom.databaseBuilder()
工厂模式 对象创建解耦 LayoutInflater.Factory2FragmentFactoryViewModelProvider.Factory
观察者模式 数据变化通知、生命周期感知 LiveData.observe()LifecycleObserverFlow.collect
适配器模式 数据和 UI 解耦 RecyclerView.AdapterListAdapterCursorAdapter
代理模式 IPC、远程服务、本地接口代理 Binder 的 Stub / Proxy、AIDL
装饰器模式 包装并增强能力 ContextWrapperContextThemeWrapperInputStream 包装链
外观模式 简化复杂子系统访问 ContextCameraXGlide.with()
模板方法模式 固定流程中暴露可重写步骤 Activity 生命周期、View.draw()ViewGroup.dispatchDraw()
策略模式 可替换算法或行为 RecyclerView.LayoutManagerItemAnimatorDiffUtil.ItemCallback
责任链模式 事件分发、拦截链 触摸事件分发、OkHttp Interceptor
状态模式 对象行为随状态变化 Lifecycle.State、播放器状态、登录状态
命令模式 把操作封装为对象 Runnable + HandlerPendingIntent、点击事件回调
MVC / MVP / MVVM 应用架构分层 Activity/FragmentViewModelLiveData/StateFlow、Repository

1. 单例模式 Singleton

使用场景

  • 应用内只有一个实例:数据库、配置中心、线程池、日志工具。
  • Android 系统服务通过统一入口获取共享服务。
  • 避免重复创建重资源对象。

Android 中的例子

  • WorkManager.getInstance(context)
  • RoomDatabase 通常在应用层做单例封装
  • SystemServiceRegistry 管理系统服务实例
  • Application 全局生命周期入口

伪代码

kotlin 复制代码
class AppDatabase private constructor() {
    companion object {
        @Volatile
        private var instance: AppDatabase? = null

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

源码 / 原理标注

  • Context.getSystemService() 背后会从系统服务注册表中按名称获取服务。
  • WorkManager 通过 getInstance() 对外提供统一入口,内部保证调度组件可被全局访问。
  • Room 数据库实例创建成本较高,官方实践通常建议在应用进程内复用单例。

2. Builder 模式

使用场景

  • 对象参数很多,构造函数会变得臃肿。
  • 创建过程需要链式配置。
  • 最终通过 build()create() 生成目标对象。

Android 中的例子

  • AlertDialog.Builder
  • NotificationCompat.Builder
  • Room.databaseBuilder(context, AppDatabase::class.java, "db").build()
  • WorkRequest.Builder

伪代码

kotlin 复制代码
class Dialog private constructor(
    val title: String?,
    val message: String?,
    val cancelable: Boolean
) {
    class Builder {
        private var title: String? = null
        private var message: String? = null
        private var cancelable: Boolean = true

        fun setTitle(value: String) = apply { title = value }
        fun setMessage(value: String) = apply { message = value }
        fun setCancelable(value: Boolean) = apply { cancelable = value }

        fun build(): Dialog {
            return Dialog(title, message, cancelable)
        }
    }
}

源码 / 原理标注

  • AlertDialog.Builder 先收集标题、按钮、布局等配置,最后调用 create() 构建 AlertDialog
  • NotificationCompat.Builder 把通知图标、标题、内容、渠道等复杂参数集中封装,降低构造复杂度。
  • Room 的 builder 会配置数据库名、迁移策略、线程策略,最后创建数据库实例。

3. 工厂模式 Factory

使用场景

  • 调用方不直接依赖具体类构造函数。
  • 根据条件创建不同对象。
  • 框架希望把对象创建权开放给开发者定制。

Android 中的例子

  • LayoutInflater.Factory2 创建 View
  • FragmentFactory 创建 Fragment
  • ViewModelProvider.Factory 创建 ViewModel
  • ServiceLoader 或依赖注入框架中的对象创建

伪代码

kotlin 复制代码
interface ViewModelFactory {
    fun <T : ViewModel> create(modelClass: Class<T>): T
}

class UserViewModelFactory(
    private val repository: UserRepository
) : ViewModelFactory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass == UserViewModel::class.java) {
            return UserViewModel(repository) as T
        }
        error("Unknown ViewModel")
    }
}

源码 / 原理标注

  • ViewModelProvider 不知道业务 ViewModel 如何构造,于是通过 Factory 把创建过程交给调用方。
  • LayoutInflater 解析 XML 时,需要把标签名转换成具体 View 对象,这就是典型的创建型模式场景。
  • FragmentFactory 允许 Fragment 使用带参数构造或依赖注入方式创建,避免框架只能调用空构造。

4. 观察者模式 Observer

使用场景

  • 一个对象状态变化,需要通知多个观察者。
  • UI 自动响应数据变化。
  • 生命周期变化需要通知监听者。

Android 中的例子

  • LiveData.observe(owner, observer)
  • Lifecycle.addObserver(observer)
  • StateFlow / SharedFlow
  • TextWatcherBroadcastReceiver

伪代码

kotlin 复制代码
class ObservableData<T> {
    private val observers = mutableListOf<(T) -> Unit>()
    private var value: T? = null

    fun observe(observer: (T) -> Unit) {
        observers += observer
        value?.let(observer)
    }

    fun setValue(newValue: T) {
        value = newValue
        observers.forEach { it(newValue) }
    }
}

源码 / 原理标注

  • LiveData 保存观察者列表,数据变化后分发给活跃生命周期状态下的观察者。
  • LifecycleRegistry 内部维护观察者,并在 Activity / Fragment 生命周期变化时派发生命周期事件。
  • BroadcastReceiver 可以理解为系统级发布订阅机制,发送广播后匹配的接收者会收到通知。

5. 适配器模式 Adapter

使用场景

  • 将一种接口转换成另一种接口。
  • 数据结构和 UI 展示组件不直接耦合。
  • 让已有数据适配目标控件协议。

Android 中的例子

  • RecyclerView.Adapter
  • ListAdapter
  • CursorAdapter
  • PagerAdapter

伪代码

kotlin 复制代码
class UserAdapter(
    private val users: List<User>
) : RecyclerView.Adapter<UserViewHolder>() {

    override fun getItemCount(): Int {
        return users.size
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
        return UserViewHolder(parent.inflate("item_user"))
    }

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

源码 / 原理标注

  • RecyclerView 不关心数据来源,只依赖 Adapter 提供数量、创建 ViewHolder、绑定数据。
  • CursorAdapter 把数据库查询结果 Cursor 适配成列表项视图。
  • ListAdapter 在适配器基础上加入 DiffUtil,让列表更新更高效。

6. 代理模式 Proxy

使用场景

  • 调用方访问的是代理对象,代理对象再转发给真实对象。
  • 可以隐藏跨进程、远程、权限校验、缓存等复杂细节。
  • Android IPC 是代理模式的经典场景。

Android 中的例子

  • Binder IPC 中的 StubProxy
  • AIDL 自动生成代码
  • 系统服务接口,例如 ActivityManagerPackageManager

伪代码

kotlin 复制代码
interface IUserService {
    fun getUserName(id: Long): String
}

class UserServiceProxy(
    private val remoteBinder: Binder
) : IUserService {
    override fun getUserName(id: Long): String {
        val data = Parcel.obtain()
        val reply = Parcel.obtain()
        data.writeLong(id)
        remoteBinder.transact(CODE_GET_USER, data, reply, 0)
        return reply.readString()
    }
}

源码 / 原理标注

  • AIDL 会生成 StubProxy:本地进程调用接口方法,实际由 Proxy 封装参数并通过 Binder 发送到远端。
  • 客户端拿到的很多系统服务接口并不是真实服务对象,而是 Binder 代理。
  • Proxy 屏蔽了进程边界,让跨进程调用看起来像普通方法调用。

7. 装饰器模式 Decorator

使用场景

  • 不修改原类的情况下增强对象能力。
  • 多层包装,逐步叠加功能。
  • 保持原始接口一致。

Android 中的例子

  • ContextWrapper
  • ContextThemeWrapper
  • Java IO 中的 BufferedInputStream(InputStream)
  • AppCompat 中对 ContextView 的包装增强

伪代码

kotlin 复制代码
open class BaseContext {
    open fun getThemeName(): String = "Default"
}

open class ContextWrapper(
    private val base: BaseContext
) : BaseContext() {
    override fun getThemeName(): String {
        return base.getThemeName()
    }
}

class ThemeContextWrapper(
    base: BaseContext,
    private val theme: String
) : ContextWrapper(base) {
    override fun getThemeName(): String {
        return theme
    }
}

源码 / 原理标注

  • ContextWrapper 内部持有一个 base Context,默认把大部分调用委托给它。
  • ContextThemeWrapper 在原有 Context 基础上叠加主题能力。
  • Activity 本身也继承自 ContextThemeWrapper,因此具备上下文和主题相关能力。

8. 外观模式 Facade

使用场景

  • 对外暴露简单接口,内部封装复杂子系统。
  • 降低调用方理解成本。
  • 常用于 SDK、框架入口、工具库入口。

Android 中的例子

  • Context 封装资源、文件、服务、启动组件等能力
  • Glide.with(context).load(url).into(imageView)
  • CameraX 相比 Camera2 提供更简单的相机 API
  • NavController 封装 Fragment 事务和回退栈

伪代码

kotlin 复制代码
class ImageLoaderFacade(
    private val cache: ImageCache,
    private val network: ImageNetwork,
    private val decoder: ImageDecoder
) {
    fun load(url: String, imageView: ImageView) {
        val bytes = cache.get(url) ?: network.download(url)
        val bitmap = decoder.decode(bytes)
        imageView.setImageBitmap(bitmap)
    }
}

源码 / 原理标注

  • Context 是 Android 应用访问系统能力的重要外观,调用方无需知道资源管理器、包管理器、服务管理器的内部细节。
  • CameraX 把 Camera2 中复杂的设备枚举、Session、CaptureRequest 封装成更容易使用的用例 API。
  • NavController 把导航图、参数、Fragment 切换、返回栈管理封装成统一入口。

9. 模板方法模式 Template Method

使用场景

  • 父类定义算法骨架。
  • 子类只重写流程中的部分步骤。
  • 框架控制整体流程,业务代码填充细节。

Android 中的例子

  • Activity.onCreate()onStart()onResume()
  • Fragment 生命周期
  • View.draw() 中的测量、绘制、子 View 绘制流程
  • BaseAdapter.getView()

伪代码

kotlin 复制代码
abstract class BaseActivity {
    fun performCreate() {
        attachBaseContext()
        onCreate()
        restoreState()
    }

    protected open fun attachBaseContext() {}
    protected abstract fun onCreate()
    protected open fun restoreState() {}
}

class MainActivity : BaseActivity() {
    override fun onCreate() {
        setContentView("activity_main")
    }
}

源码 / 原理标注

  • Android Framework 决定生命周期调用顺序,开发者只重写指定回调。
  • View.draw() 内部大致按背景、内容、子 View、前景等步骤绘制,子类可重写 onDraw() 填充自定义绘制。
  • 模板方法体现了"框架调用业务代码"的控制反转思想。

10. 策略模式 Strategy

使用场景

  • 同一个上下文中切换不同算法或行为。
  • 行为对象可以独立替换。
  • 减少大量 if else

Android 中的例子

  • RecyclerView.LayoutManager
  • RecyclerView.ItemAnimator
  • DiffUtil.ItemCallback
  • 动画插值器 Interpolator

伪代码

kotlin 复制代码
interface SortStrategy {
    fun sort(items: List<Item>): List<Item>
}

class TimeSortStrategy : SortStrategy {
    override fun sort(items: List<Item>) = items.sortedBy { it.time }
}

class NameSortStrategy : SortStrategy {
    override fun sort(items: List<Item>) = items.sortedBy { it.name }
}

class ItemController(
    private var strategy: SortStrategy
) {
    fun render(items: List<Item>) {
        show(strategy.sort(items))
    }
}

源码 / 原理标注

  • RecyclerView 通过替换 LinearLayoutManagerGridLayoutManagerStaggeredGridLayoutManager 改变布局策略。
  • Interpolator 决定动画数值随时间变化的策略,例如线性、加速、减速。
  • DiffUtil.ItemCallback 把"如何判断两个 item 是否相同"的策略交给业务层。

11. 责任链模式 Chain of Responsibility

使用场景

  • 请求沿着一条链传递。
  • 链上每个节点都有机会处理或继续传递。
  • 常用于事件分发、请求拦截、日志处理。

Android 中的例子

  • 触摸事件分发:Activity -> Window -> DecorView -> ViewGroup -> View
  • ViewGroup.dispatchTouchEvent()onInterceptTouchEvent()onTouchEvent()
  • OkHttp Interceptor 拦截器链

伪代码

kotlin 复制代码
abstract class EventNode {
    var next: EventNode? = null

    fun dispatch(event: MotionEvent): Boolean {
        if (handle(event)) {
            return true
        }
        return next?.dispatch(event) ?: false
    }

    protected abstract fun handle(event: MotionEvent): Boolean
}

源码 / 原理标注

  • 触摸事件先到 Activity.dispatchTouchEvent(),再进入 Window 和根 View。
  • ViewGroup 可以通过 onInterceptTouchEvent() 决定是否拦截事件。
  • 如果子 View 不消费事件,事件可能回到父容器或自身的 onTouchEvent() 继续处理。
  • OkHttp 的应用拦截器、重试拦截器、缓存拦截器、网络拦截器按链式顺序处理请求。

12. 状态模式 State

使用场景

  • 对象在不同状态下行为不同。
  • 状态转换规则比较清晰。
  • 避免状态相关逻辑散落在多个条件分支中。

Android 中的例子

  • Lifecycle.State
  • 播放器状态:Idle、Preparing、Playing、Paused、Completed
  • 登录状态:Guest、LoggedIn、Expired
  • 下载任务状态:Pending、Running、Success、Failed

伪代码

kotlin 复制代码
interface PlayerState {
    fun play(player: Player)
    fun pause(player: Player)
}

class IdleState : PlayerState {
    override fun play(player: Player) {
        player.prepare()
        player.state = PlayingState()
    }

    override fun pause(player: Player) {
        // Idle 状态下无需处理
    }
}

class PlayingState : PlayerState {
    override fun play(player: Player) {}

    override fun pause(player: Player) {
        player.pauseInternal()
        player.state = PausedState()
    }
}

源码 / 原理标注

  • LifecycleRegistry 会在生命周期事件发生时推进内部状态,例如 INITIALIZEDCREATEDSTARTEDRESUMED
  • UI 层常用状态驱动渲染,例如 Loading、Content、Empty、Error。
  • 播放器、下载器、上传器这类组件很适合用状态模式管理行为。

13. 命令模式 Command

使用场景

  • 把一个操作封装成对象。
  • 操作可以延迟执行、排队执行、撤销或重试。
  • 调用者和执行者解耦。

Android 中的例子

  • Runnable 投递到 Handler
  • PendingIntent
  • View.OnClickListener
  • WorkRequest

伪代码

kotlin 复制代码
interface Command {
    fun execute()
}

class SaveUserCommand(
    private val repository: UserRepository,
    private val user: User
) : Command {
    override fun execute() {
        repository.save(user)
    }
}

class CommandQueue {
    private val commands = ArrayDeque<Command>()

    fun enqueue(command: Command) {
        commands.addLast(command)
    }

    fun runNext() {
        commands.removeFirstOrNull()?.execute()
    }
}

源码 / 原理标注

  • Handler.post(Runnable) 把一段逻辑封装为 Runnable,放入消息队列等待主线程或工作线程执行。
  • PendingIntent 把未来要执行的启动 Activity、Service、Broadcast 操作交给系统保存并触发。
  • WorkRequest 把后台任务的执行条件、输入数据、调度要求封装起来,由 WorkManager 统一执行。

14. MVC / MVP / MVVM 架构模式

使用场景

  • 组织应用层代码职责。
  • 降低 UI、业务逻辑、数据源之间的耦合。
  • 提高可测试性和可维护性。

Android 中的例子

  • MVC:早期 Activity 同时承担 Controller 和部分 View 职责。
  • MVP:Activity/Fragment 作为 View,Presenter 处理业务逻辑。
  • MVVM:ViewModel 暴露状态,Activity/Fragment/Compose 负责渲染。
  • Repository:隔离网络、数据库、缓存等数据来源。

伪代码

kotlin 复制代码
class UserViewModel(
    private val repository: UserRepository
) : ViewModel() {
    private val _uiState = MutableStateFlow<UserUiState>(UserUiState.Loading)
    val uiState: StateFlow<UserUiState> = _uiState

    fun loadUser(id: Long) {
        viewModelScope.launch {
            _uiState.value = UserUiState.Loading
            _uiState.value = runCatching {
                repository.getUser(id)
            }.fold(
                onSuccess = { UserUiState.Content(it) },
                onFailure = { UserUiState.Error(it.message.orEmpty()) }
            )
        }
    }
}

class UserFragment : Fragment() {
    private val viewModel: UserViewModel by viewModels()

    fun render() {
        collect(viewModel.uiState) { state ->
            when (state) {
                is UserUiState.Loading -> showLoading()
                is UserUiState.Content -> showUser(state.user)
                is UserUiState.Error -> showError(state.message)
            }
        }
    }
}

源码 / 原理标注

  • ViewModel 生命周期长于配置变化后的 Activity/Fragment 重建,适合保存 UI 状态。
  • LiveData / StateFlow 让 View 观察状态变化,体现观察者模式。
  • Repository 隔离数据来源,让 UI 层不直接依赖 Retrofit、Room、DataStore 等具体实现。
  • Jetpack Compose 中常见的 State -> UI 思路也是 MVVM / 单向数据流思想的延伸。

15. 组合模式 Composite

使用场景

  • 树形结构中,单个对象和组合对象使用统一接口。
  • 调用方可以一致地处理叶子节点和容器节点。

Android 中的例子

  • ViewViewGroup
  • 菜单结构 Menu / MenuItem
  • Compose UI 树

伪代码

kotlin 复制代码
abstract class UiNode {
    abstract fun draw()
}

class TextNode : UiNode() {
    override fun draw() {
        drawText()
    }
}

class ContainerNode : UiNode() {
    private val children = mutableListOf<UiNode>()

    fun add(child: UiNode) {
        children += child
    }

    override fun draw() {
        children.forEach { it.draw() }
    }
}

源码 / 原理标注

  • ViewGroup 继承自 View,因此容器本身也是一个 View。
  • ViewGroup 内部持有子 View 列表,测量、布局、绘制时会递归处理子节点。
  • Compose 运行时维护 UI 组合树,状态变化后按树结构进行重组和更新。

16. 享元模式 Flyweight

使用场景

  • 大量相似对象共享内部状态,减少内存开销。
  • 缓存可复用对象。
  • 图片、字符串、资源对象等都可能用到共享思想。

Android 中的例子

  • Bitmap 缓存
  • RecyclerView 复用 ViewHolder
  • 资源系统复用 DrawableColorStateList 等资源数据
  • 字符串常量池

伪代码

kotlin 复制代码
class BitmapPool {
    private val cache = mutableMapOf<String, Bitmap>()

    fun get(key: String, loader: () -> Bitmap): Bitmap {
        return cache[key] ?: loader().also { bitmap ->
            cache[key] = bitmap
        }
    }
}

源码 / 原理标注

  • RecyclerView 通过回收池复用 ViewHolder,避免列表滑动时频繁创建 View。
  • 图片加载库通常使用内存缓存、磁盘缓存、Bitmap 池降低内存抖动。
  • Android 资源加载系统会缓存部分资源,避免重复解析和创建。

记忆方式

你在做什么 常见模式
创建复杂对象 Builder
控制对象唯一 Singleton
把创建权交出去 Factory
数据变了通知 UI Observer
数据接到列表控件 Adapter
跨进程像本地调用 Proxy
包一层增强功能 Decorator
给复杂系统一个简单入口 Facade
框架定流程,业务填步骤 Template Method
替换算法或行为 Strategy
请求一路传递 Chain of Responsibility
不同状态不同行为 State
操作排队或延迟执行 Command
树形 UI 统一处理 Composite
大量对象共享复用 Flyweight

学习建议

  • 看源码时先问:这个类是在创建对象、转发调用、分发事件、保存状态,还是适配数据?
  • Android Framework 很多模式不是"标准教科书写法",而是为了生命周期、IPC、UI 树、线程模型做了工程化变体。
  • 面试回答时建议按"三段式":先说模式定义,再说 Android 例子,最后说源码或原理中的关键调用链。
相关推荐
sickworm陈浩1 小时前
日常修改,3秒生效:腾讯音乐 Android 秒编方案 Jugg 开源
android·编译原理·编译器
Android-Flutter1 小时前
android PhoneWindow, DecorView 详解
android
宝杰X72 小时前
Android Umeng 16kb对齐
android
2601_966563522 小时前
NativeWasmTv超精简2m安装包 长效免费电视直播软件-支持老电视盒子安卓4.0
android·电视盒子
Knight_AL2 小时前
MySQL 递归 CTE:WITH RECURSIVE 用法详解
android·数据库·mysql
恋猫de小郭2 小时前
聊个比较有意思的 Flutter Web 问题
android·前端·flutter
stevenzqzq2 小时前
Compose 生命周期与副作用的核心奥秘
android·compose
2501_915918412 小时前
Flutter项目配置iOS混淆的详细步骤与工具推荐
android·flutter·ios·小程序·uni-app·cocoa·iphone
天空之城--2 小时前
过去一周Android行业动态:编码技术与综合趋势精选
android·flutter·性能优化·kotlin·android jetpack