一、Android 中常见的设计模式
1. 单例模式 Singleton
作用
保证一个类只有一个实例,并提供全局访问点。
Android 中常见场景
ApplicationSharedPreferencesRoomDatabaseRetrofitOkHttpClient- 图片加载库实例
- 全局配置管理类
示例
public class AppManager {
private static volatile AppManager instance;
private AppManager() {}
public static AppManager getInstance() {
if (instance == null) {
synchronized (AppManager.class) {
if (instance == null) {
instance = new AppManager();
}
}
}
return instance;
}
}
面试常问
问:单例模式有哪几种写法?
常见写法:
- 饿汉式
- 懒汉式
- 双重检查锁 DCL
- 静态内部类
- 枚举单例
问:DCL 为什么要加 volatile?
因为创建对象不是原子操作,大致分为:
1. 分配内存
2. 初始化对象
3. 将引用指向内存
如果发生指令重排序,可能变成:
1. 分配内存
2. 引用指向内存
3. 初始化对象
其他线程可能拿到一个还没初始化完成的对象。
volatile 可以禁止指令重排序,保证可见性。
2. Builder 建造者模式
作用
用于创建复杂对象,避免构造方法参数过多。
Android 中常见场景
AlertDialog.BuilderNotification.BuilderOkHttpClient.BuilderRetrofit.BuilderGlide.with().load().into()
示例
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle("提示")
.setMessage("确定删除吗?")
.setPositiveButton("确定", null)
.setNegativeButton("取消", null)
.create();
优点
- 代码可读性好
- 参数灵活
- 适合创建复杂对象
面试常问
问:Builder 模式和构造方法相比有什么优势?
答:
如果对象参数很多,构造方法会变得很长:
new User("Tom", 18, "男", "北京", "123456");
可读性差,也容易传错参数。
Builder 写法更清晰:
User user = new User.Builder()
.name("Tom")
.age(18)
.gender("男")
.address("北京")
.phone("123456")
.build();
3. 工厂模式 Factory
作用
把对象创建逻辑封装起来,调用者不需要关心具体创建细节。
Android 中常见场景
BitmapFactoryLayoutInflater.from(context)ViewModelProvider.FactoryFragmentFactoryThreadFactory
示例
public class ShapeFactory {
public static Shape createShape(String type) {
if ("circle".equals(type)) {
return new Circle();
} else if ("rect".equals(type)) {
return new Rect();
}
return null;
}
}
面试常问
问:简单工厂、工厂方法、抽象工厂有什么区别?
简单理解:
| 类型 | 特点 |
|---|---|
| 简单工厂 | 一个工厂类根据参数创建不同对象 |
| 工厂方法 | 每个产品对应一个工厂子类 |
| 抽象工厂 | 创建一组相关对象 |
4. 观察者模式 Observer
作用
一个对象状态变化时,自动通知依赖它的对象。
Android 中常见场景
LiveDataRxJavaFlowEventBusBroadcastReceiverTextWatcherOnClickListenerRecyclerView.AdapterDataObserver
示例
button.setOnClickListener(v -> {
// 点击事件回调
});
这其实就是一种观察者模式:
Button 是被观察者
OnClickListener 是观察者
点击事件发生后通知 listener
LiveData 示例
viewModel.userLiveData.observe(this, user -> {
textView.setText(user.getName());
});
面试常问
问:观察者模式和发布订阅模式有什么区别?
答:
观察者模式中,观察者和被观察者通常直接关联。
Subject 持有 Observer 列表
发布订阅模式中,中间多了一个事件中心。
Publisher -> EventBus -> Subscriber
所以发布订阅模式解耦更强。
5. 适配器模式 Adapter
作用
把一个类的接口转换成客户端期望的接口。
Android 中常见场景
RecyclerView.AdapterListView.AdapterPagerAdapterFragmentStateAdapterSpinnerAdapter
示例
RecyclerView.Adapter 的作用就是:
把数据 List<T> 适配成 RecyclerView 可以显示的 ViewHolder
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserViewHolder> {
private List<User> users;
}
面试常问
问:RecyclerView.Adapter 是什么设计模式?
答:
主要是适配器模式。
它负责把数据源适配成 RecyclerView 能展示的 Item View。
同时,ViewHolder 又体现了缓存复用思想。
6. ViewHolder 模式
严格来说,ViewHolder 不一定算 GoF 经典设计模式,但 Android 面试很常见。
作用
缓存 Item 中的 View,避免频繁 findViewById(),提升列表滑动性能。
常见场景
ListViewRecyclerView
示例
static class ViewHolder extends RecyclerView.ViewHolder {
TextView name;
public ViewHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.tv_name);
}
}
面试常问
问:RecyclerView 为什么比 ListView 性能更好?
答:
- 强制使用 ViewHolder
- 支持更灵活的布局管理器
- 支持局部刷新
- 支持 Item 动画
- 缓存机制更完善
7. 代理模式 Proxy
作用
为其他对象提供一种代理,以控制对这个对象的访问。
Android 中常见场景
- Binder 机制中的 Proxy/Stub
- AIDL 生成代码
- Retrofit 动态代理
- Hook 技术
ContextWrapper
AIDL 中的代理模式
客户端拿到的是远程服务的代理对象:
客户端 Proxy -> Binder 驱动 -> 服务端 Stub
客户端调用方法,看起来像普通方法调用:
service.getUserName();
实际底层是:
mRemote.transact(...)
面试常问
问:AIDL 中 Stub 和 Proxy 分别是什么?
答:
Stub:服务端 Binder 对象,负责接收请求并分发到具体方法。Proxy:客户端代理对象,负责把方法调用转换成 Binder 的transact()。
8. 装饰者模式 Decorator
作用
在不改变原对象结构的情况下,动态增强对象功能。
Android 中常见场景
ContextWrapperContextThemeWrapperBufferedInputStreamDataInputStream- OkHttp 中的拦截器也有类似增强思想
示例
ContextWrapper wrapper = new ContextWrapper(context);
ContextWrapper 包装了一个真实的 Context,并可以增强或修改部分行为。
面试常问
问:代理模式和装饰者模式区别?
答:
| 对比 | 代理模式 | 装饰者模式 |
|---|---|---|
| 目的 | 控制访问 | 增强功能 |
| 关注点 | 是否允许访问、远程访问、懒加载等 | 给对象添加新能力 |
| 例子 | Binder Proxy | ContextWrapper |
9. 外观模式 Facade
作用
对外提供一个简单接口,隐藏内部复杂实现。
Android 中常见场景
ContextMediaPlayerGlideRetrofit- 各种 Manager 类
示例
Glide.with(context)
.load(url)
.into(imageView);
调用者只需要一行代码,不需要关心:
- 网络请求
- 图片解码
- 缓存
- 线程切换
- Bitmap 复用
这些复杂逻辑都被 Glide 封装起来了。
10. 策略模式 Strategy
作用
定义一组算法,把它们封装起来,使它们可以互相替换。
Android 中常见场景
InterpolatorRecyclerView.LayoutManager- 图片加载策略
- 缓存策略
- 排序策略
- 支付方式选择
示例
animation.setInterpolator(new AccelerateInterpolator());
不同的插值器表示不同动画变化策略:
new LinearInterpolator()
new AccelerateInterpolator()
new DecelerateInterpolator()
面试常问
问:策略模式和工厂模式有什么区别?
答:
- 工厂模式关注“创建对象”
- 策略模式关注“行为算法的替换”
11. 模板方法模式 Template Method
作用
父类定义算法骨架,子类实现具体步骤。
Android 中常见场景
Activity生命周期Fragment生命周期AsyncTask- 自定义 View 的绘制流程
示例
Activity 生命周期:
onCreate()
onStart()
onResume()
onPause()
onStop()
onDestroy()
系统定义整体流程,开发者重写其中某些方法。
自定义 View
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 自定义绘制
}
面试常问
问:Activity 生命周期体现了什么设计模式?
答:
模板方法模式。
Android Framework 定义生命周期调用流程,开发者通过重写生命周期方法插入自己的逻辑。
12. 责任链模式 Chain of Responsibility
作用
多个对象按链式顺序处理请求,直到某个对象处理为止。
Android 中常见场景
- View 事件分发
- OkHttp 拦截器
- Touch 事件传递
- Handler 消息机制有部分链式思想
View 事件分发
Activity
-> Window
-> DecorView
-> ViewGroup
-> View
事件依次传递:
dispatchTouchEvent()
onInterceptTouchEvent()
onTouchEvent()
OkHttp 拦截器
应用拦截器
-> 重试重定向拦截器
-> BridgeInterceptor
-> CacheInterceptor
-> ConnectInterceptor
-> CallServerInterceptor
面试常问
问:Android 事件分发是什么设计模式?
答:
主要体现责任链模式。
事件从 Activity 一层层向下分发,每一层都有机会处理或拦截事件。
13. 享元模式 Flyweight
作用
共享对象,减少内存占用。
Android 中常见场景
Message.obtain()Handler消息池RecyclerView复用 ItemView- Bitmap 缓存
- 字符串常量池
Message 示例
Message msg = Message.obtain();
比直接:
new Message();
更好,因为 Message.obtain() 会从消息池中复用对象,减少频繁创建和 GC。
面试常问
问:Handler 的 Message 为什么推荐使用 obtain?
答:
因为 Message.obtain() 会复用消息池中的 Message 对象,减少内存分配和 GC,提高性能。
14. MVC / MVP / MVVM 架构模式
这类不属于传统 GoF 设计模式,但 Android 面试非常常见。
二、Android 架构模式
1. MVC
结构
Model:数据层
View:界面层
Controller:控制层
Android 中的问题
Activity/Fragment 往往同时承担 View 和 Controller,导致代码臃肿。
Activity 既处理 UI,又处理业务逻辑
所以容易变成:
Massive Activity
2. MVP
结构
Model:数据
View:界面接口
Presenter:业务逻辑
特点
View 和 Model 不直接通信,通过 Presenter 中转。
View <-> Presenter <-> Model
优点
- 降低 Activity/Fragment 复杂度
- 便于单元测试
- 职责清晰
缺点
- 接口类多
- Presenter 容易膨胀
- 生命周期处理麻烦
3. MVVM
结构
Model:数据层
View:Activity/Fragment/XML
ViewModel:状态和业务逻辑
Android 常见组合
ViewModel + LiveData/StateFlow + DataBinding/ViewBinding
特点
View 观察 ViewModel 中的数据变化。
viewModel.userLiveData.observe(this, user -> {
textView.setText(user.name);
});
优点
- 生命周期感知
- UI 和数据状态分离
- 配合 Jetpack 使用方便
- 适合响应式开发
面试常问
问:MVP 和 MVVM 的区别?
| 对比 | MVP | MVVM |
|---|---|---|
| 中间层 | Presenter | ViewModel |
| View 更新 | Presenter 主动调用 View 接口 | View 观察数据变化 |
| 生命周期 | 需要自己处理 | ViewModel 生命周期感知 |
| 耦合 | Presenter 持有 View 接口 | ViewModel 不应持有 View |
| 常用技术 | 接口回调 | LiveData / Flow / DataBinding |
三、Android 设计模式高频面试题
1. Android 中哪些地方用到了单例模式?
常见回答:
ApplicationRuntimeInputMethodManagerLayoutInflater.from(context)内部缓存OkHttpClientRetrofit- 数据库管理类
- 图片加载框架管理类
注意:
Application 本身由系统创建,通常整个 App 进程只有一个实例,但它不是我们手写的标准单例。
2. AlertDialog.Builder 用的什么模式?
答:
Builder 建造者模式。
它通过链式调用一步步设置参数,最后通过:
create()
show()
创建或显示 Dialog。
3. RecyclerView.Adapter 是什么设计模式?
答:
适配器模式。
它把数据集合适配成 RecyclerView 可以识别和展示的 ViewHolder。
4. View 事件分发是什么设计模式?
答:
责任链模式。
事件从 Activity、Window、DecorView、ViewGroup 到 View 逐层传递,每一层都可以决定是否消费或继续分发。
5. AIDL/Binder 用到了什么设计模式?
答:
主要是代理模式。
客户端拿到的是服务端 Binder 的代理对象 Proxy,方法调用会被转换成 Binder IPC 请求。
同时服务端的 Stub 负责接收请求并分发。
6. LiveData 是什么设计模式?
答:
观察者模式。
Activity/Fragment 观察 LiveData,当数据变化时,LiveData 通知观察者更新 UI。
7. BroadcastReceiver 是什么设计模式?
答:
观察者模式或发布订阅模式。
广播发送者不直接依赖接收者,系统广播机制负责分发事件。
8. OkHttp 拦截器是什么设计模式?
答:
责任链模式。
每个 Interceptor 处理请求的一部分,然后通过:
chain.proceed(request)
交给下一个拦截器。
9. Glide.with().load().into() 体现了什么模式?
可以回答:
- 外观模式:封装复杂图片加载逻辑
- Builder/链式调用:配置请求参数
- 观察者/回调:监听加载结果
- 缓存中可能用到享元思想
面试中主答:
Glide 对外提供了简单 API,隐藏内部复杂的网络、缓存、解码、线程调度流程,体现了外观模式。
10. Handler 消息机制中用到了什么设计模式?
可以回答:
- 享元模式:
Message.obtain()复用 Message - 生产者消费者模型:发送消息和处理消息
- 观察者/回调思想:Handler 处理 Message 或 Runnable
- Looper 不一定是标准单例,但一个线程通常只有一个 Looper
四、常见设计模式速记表
| 设计模式 | Android 典型例子 |
|---|---|
| 单例模式 | Retrofit、OkHttpClient、RoomDatabase |
| Builder 模式 | AlertDialog.Builder、Notification.Builder |
| 工厂模式 | BitmapFactory、LayoutInflater |
| 观察者模式 | LiveData、RxJava、OnClickListener |
| 适配器模式 | RecyclerView.Adapter、ListView.Adapter |
| 代理模式 | AIDL、Binder Proxy、Retrofit |
| 装饰者模式 | ContextWrapper、BufferedInputStream |
| 外观模式 | Glide、Retrofit、Context |
| 策略模式 | Interpolator、LayoutManager |
| 模板方法模式 | Activity 生命周期、自定义 View |
| 责任链模式 | 事件分发、OkHttp Interceptor |
| 享元模式 | Message.obtain、RecyclerView 复用 |
五、面试回答模板
如果面试官问:
Android 中你知道哪些设计模式?
可以这样回答:
Android 中常见设计模式有很多。
比如单例模式,常用于 Retrofit、OkHttp、数据库管理类;
Builder 模式,比如 AlertDialog.Builder;
适配器模式,比如 RecyclerView.Adapter;
观察者模式,比如 LiveData、OnClickListener、BroadcastReceiver;
代理模式,比如 AIDL 中的 Stub 和 Proxy;
责任链模式,比如 View 事件分发和 OkHttp 拦截器;
模板方法模式,比如 Activity 生命周期;
享元模式,比如 Handler 的 Message.obtain();
策略模式,比如动画 Interpolator 和 RecyclerView.LayoutManager。
这些模式主要是为了解耦、复用、扩展和提高代码可维护性。
如果想加分,可以继续说:
我在项目中常用的是 MVVM 架构,ViewModel 负责保存 UI 状态,LiveData 或 StateFlow 负责数据通知,Repository 负责数据来源封装,这里面也结合了观察者模式、单例模式、工厂模式等思想。