一句话说透Android里面的策略模式

152 阅读3分钟

一句话总结:
策略模式就像「游戏技能栏」—— 随时切换不同技能(算法),Android 里的动画插值器、RecyclerView 布局都用它动态调整核心逻辑!


一、策略模式的核心思想

核心要素

  • 策略接口:定义算法规范(如 TimeInterpolator
  • 具体策略:实现不同算法(如 LinearInterpolatorBounceInterpolator
  • 环境类:持有策略引用并执行(如 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 布局换,插值器让动画浪

使用场景建议

  1. 需要动态切换算法(如不同加密策略)
  2. 存在多重条件分支选择不同行为
  3. 希望隔离算法实现与使用代码

注意事项

  1. 避免策略类膨胀(超过 10 个策略建议用工厂管理)
  2. 策略对象无状态时可设计为单例
  3. 优先组合而非继承(如 RecyclerView 组合 LayoutManager

源码对照表

场景策略接口具体策略实现
动画插值TimeInterpolatorLinearInterpolator
布局管理LayoutManagerGridLayoutManager
图片加载策略DiskCacheStrategyAUTOMATIC/RESOURCE