Android 常用设计模式速查
本文整理 Android 开发中常见技术点对应的设计模式,并给出简化伪代码、典型源码/原理使用位置。伪代码用于理解模式结构,不等同于源码实现。
总览
| 设计模式 |
Android 常见技术点 |
典型使用位置 |
| 单例模式 |
全局管理器、系统服务、数据库实例 |
WorkManager.getInstance()、Room.databaseBuilder() 后的数据库单例、SystemServiceRegistry |
| Builder 模式 |
复杂对象构建 |
AlertDialog.Builder、NotificationCompat.Builder、Room.databaseBuilder() |
| 工厂模式 |
对象创建解耦 |
LayoutInflater.Factory2、FragmentFactory、ViewModelProvider.Factory |
| 观察者模式 |
数据变化通知、生命周期感知 |
LiveData.observe()、LifecycleObserver、Flow.collect |
| 适配器模式 |
数据和 UI 解耦 |
RecyclerView.Adapter、ListAdapter、CursorAdapter |
| 代理模式 |
IPC、远程服务、本地接口代理 |
Binder 的 Stub / Proxy、AIDL |
| 装饰器模式 |
包装并增强能力 |
ContextWrapper、ContextThemeWrapper、InputStream 包装链 |
| 外观模式 |
简化复杂子系统访问 |
Context、CameraX、Glide.with() |
| 模板方法模式 |
固定流程中暴露可重写步骤 |
Activity 生命周期、View.draw()、ViewGroup.dispatchDraw() |
| 策略模式 |
可替换算法或行为 |
RecyclerView.LayoutManager、ItemAnimator、DiffUtil.ItemCallback |
| 责任链模式 |
事件分发、拦截链 |
触摸事件分发、OkHttp Interceptor |
| 状态模式 |
对象行为随状态变化 |
Lifecycle.State、播放器状态、登录状态 |
| 命令模式 |
把操作封装为对象 |
Runnable + Handler、PendingIntent、点击事件回调 |
| MVC / MVP / MVVM |
应用架构分层 |
Activity/Fragment、ViewModel、LiveData/StateFlow、Repository |
1. 单例模式 Singleton
使用场景
- 应用内只有一个实例:数据库、配置中心、线程池、日志工具。
- Android 系统服务通过统一入口获取共享服务。
- 避免重复创建重资源对象。
Android 中的例子
WorkManager.getInstance(context)
RoomDatabase 通常在应用层做单例封装
SystemServiceRegistry 管理系统服务实例
Application 全局生命周期入口
伪代码
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
伪代码
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 或依赖注入框架中的对象创建
伪代码
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
TextWatcher、BroadcastReceiver
伪代码
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
伪代码
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 中的
Stub 和 Proxy
- AIDL 自动生成代码
- 系统服务接口,例如
ActivityManager、PackageManager
伪代码
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 会生成
Stub 和 Proxy:本地进程调用接口方法,实际由 Proxy 封装参数并通过 Binder 发送到远端。
- 客户端拿到的很多系统服务接口并不是真实服务对象,而是 Binder 代理。
Proxy 屏蔽了进程边界,让跨进程调用看起来像普通方法调用。
7. 装饰器模式 Decorator
使用场景
- 不修改原类的情况下增强对象能力。
- 多层包装,逐步叠加功能。
- 保持原始接口一致。
Android 中的例子
ContextWrapper
ContextThemeWrapper
- Java IO 中的
BufferedInputStream(InputStream)
- AppCompat 中对
Context 和 View 的包装增强
伪代码
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 事务和回退栈
伪代码
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()
伪代码
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
伪代码
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 通过替换 LinearLayoutManager、GridLayoutManager、StaggeredGridLayoutManager 改变布局策略。
Interpolator 决定动画数值随时间变化的策略,例如线性、加速、减速。
DiffUtil.ItemCallback 把"如何判断两个 item 是否相同"的策略交给业务层。
11. 责任链模式 Chain of Responsibility
使用场景
- 请求沿着一条链传递。
- 链上每个节点都有机会处理或继续传递。
- 常用于事件分发、请求拦截、日志处理。
Android 中的例子
- 触摸事件分发:
Activity -> Window -> DecorView -> ViewGroup -> View
ViewGroup.dispatchTouchEvent()、onInterceptTouchEvent()、onTouchEvent()
OkHttp Interceptor 拦截器链
伪代码
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
伪代码
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 会在生命周期事件发生时推进内部状态,例如 INITIALIZED、CREATED、STARTED、RESUMED。
- UI 层常用状态驱动渲染,例如 Loading、Content、Empty、Error。
- 播放器、下载器、上传器这类组件很适合用状态模式管理行为。
13. 命令模式 Command
使用场景
- 把一个操作封装成对象。
- 操作可以延迟执行、排队执行、撤销或重试。
- 调用者和执行者解耦。
Android 中的例子
Runnable 投递到 Handler
PendingIntent
View.OnClickListener
WorkRequest
伪代码
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:隔离网络、数据库、缓存等数据来源。
伪代码
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 中的例子
View 和 ViewGroup
- 菜单结构
Menu / MenuItem
- Compose UI 树
伪代码
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
- 资源系统复用
Drawable、ColorStateList 等资源数据
- 字符串常量池
伪代码
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 例子,最后说源码或原理中的关键调用链。