一句话总结:
策略模式就像「游戏技能栏」—— 随时切换不同技能(算法),Android 里的动画插值器、RecyclerView 布局都用它动态调整核心逻辑!
一、策略模式的核心思想
核心要素:
- 策略接口:定义算法规范(如
TimeInterpolator) - 具体策略:实现不同算法(如
LinearInterpolator、BounceInterpolator) - 环境类:持有策略引用并执行(如
ValueAnimator)
类比场景:
- 玩家(环境类)根据战况切换技能(具体策略)
- 技能效果独立开发,玩家只负责触发
二、Android 源码中的策略模式案例
1. 动画插值器(Interpolator)
源码实现:
// 策略接口
public interface TimeInterpolator {
float getInterpolation(float input);
}
// 具体策略:线性插值
public class LinearInterpolator implements TimeInterpolator {
public float getInterpolation(float input) {
return input; // 匀速动画
}
}
// 具体策略:弹性插值
public class BounceInterpolator implements TimeInterpolator {
public float getInterpolation(float input) {
// 弹性计算逻辑(此处简化)
return (float)(Math.sin(input * Math.PI * 2) * 0.3);
}
}
// 环境类:ValueAnimator 使用策略
ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
anim.setInterpolator(new BounceInterpolator()); // 动态切换策略
anim.start();
设计亮点:
- 插值逻辑与动画引擎解耦
- 运行时自由替换效果(无需修改
ValueAnimator源码)
2. RecyclerView 的布局策略(LayoutManager)
源码结构:
// 策略接口
public abstract class LayoutManager {
public abstract void onLayoutChildren(Recycler recycler, State state);
// 其他布局相关方法...
}
// 具体策略:线性布局
public class LinearLayoutManager extends LayoutManager {
@Override
public void onLayoutChildren(Recycler recycler, State state) {
// 实现列表布局逻辑
}
}
// 具体策略:网格布局
public class GridLayoutManager extends LinearLayoutManager {
@Override
public void onLayoutChildren(Recycler recycler, State state) {
// 实现网格布局逻辑
}
}
// 环境类:RecyclerView 设置策略
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new GridLayoutManager(context, 2)); // 动态切换布局
底层原理:
RecyclerView通过mLayout成员持有当前布局策略- 调用
requestLayout()时触发当前策略的onLayoutChildren
三、策略模式的优势与源码设计亮点
1. 开闭原则的完美实践
- 扩展开放:新增布局类型只需继承
LayoutManager - 修改关闭:
RecyclerView无需修改源码即可支持新布局
2. 性能优化技巧
// RecyclerView 缓存布局策略的计算结果
public void onLayoutChildren(Recycler recycler, State state) {
if (mPendingSavedState != null) {
// 复用已保存的布局状态
}
// 计算并缓存 View 位置
layoutChunk(recycler, state, layoutState, layoutChunkResult);
}
3. 资源隔离机制
// 不同策略使用独立配置参数
public static class LayoutParams extends RecyclerView.LayoutParams {
// 网格布局特有的行列跨度参数
int mSpanIndex = INVALID_SPAN_ID;
int mSpanSize = 0;
}
四、策略模式的实际应用场景
1. 网络请求策略切换
// 定义策略接口
public interface CacheStrategy {
Response getCache(String key);
void saveCache(String key, Response response);
}
// 具体策略:内存缓存
public class MemoryCache implements CacheStrategy { ... }
// 具体策略:磁盘缓存
public class DiskCache implements CacheStrategy { ... }
// 环境类使用策略
public class NetworkClient {
private CacheStrategy cacheStrategy;
public void setCacheStrategy(CacheStrategy strategy) {
this.cacheStrategy = strategy;
}
public Response fetchData(String url) {
Response cache = cacheStrategy.getCache(url);
if (cache != null) return cache;
// 执行网络请求...
}
}
2. 图片加载策略选择
// Glide 根据网络状态切换策略
RequestBuilder<Drawable> request = Glide.with(context)
.load(url)
.apply(new RequestOptions()
.diskCacheStrategy(isWifi ? DiskCacheStrategy.AUTOMATIC : DiskCacheStrategy.NONE)
);
五、策略模式与相似模式对比
| 模式 | 核心区别 | Android 案例 |
|---|---|---|
| 策略模式 | 动态切换算法逻辑 | LayoutManager、Interpolator |
| 状态模式 | 行为随内部状态改变 | WifiManager 连接状态管理 |
| 工厂模式 | 创建对象,不关注行为逻辑 | BitmapFactory |
六、总结口诀
「算法多变用策略,布局动画好替换
接口定义规范在,具体实现随便改
RecyclerView 布局换,插值器让动画浪
使用场景建议:
- 需要动态切换算法(如不同加密策略)
- 存在多重条件分支选择不同行为
- 希望隔离算法实现与使用代码
注意事项:
- 避免策略类膨胀(超过 10 个策略建议用工厂管理)
- 策略对象无状态时可设计为单例
- 优先组合而非继承(如
RecyclerView组合LayoutManager)
源码对照表:
| 场景 | 策略接口 | 具体策略实现 |
|---|---|---|
| 动画插值 | TimeInterpolator | LinearInterpolator |
| 布局管理 | LayoutManager | GridLayoutManager |
| 图片加载策略 | DiskCacheStrategy | AUTOMATIC/RESOURCE |