策略模式也是经常使用到的模式之一,常用于需要多种算法、配置的场景。
模式概况
- 实际需求
- 一个业务有多种解决方案,需要根据实际情况动态配置
- 避免过多地分支判断
- 解决方案
- 将“解决方案”分别打包,外部自行调用
- 详细设计
- 抽象共有接口
策略模式重在封装一个完整的算法或方案,各个方案之间可以相互替换,不影响外部业务逻辑。
从某种意义上来说,策略模式就是把一整套算法或逻辑封装成一个“参数”,可以在特定的方法里传入。
模式实现
假如我这里的业务是需要对一组数据进行排序,那么先抽象出接口:
public interface ISortStrategy {
void sort(int[] origin);
}
然后依据现有的解决方案,实现几个排序算法:
public class InsertSort implements ISortStrategy {
@Override
public void sort(int[] origin) {
//插入排序
}
}
}
public class QuickSort implements ISortStrategy {
@Override
public void sort(int[] origin) {
//快速排序
}
}
最后是使用的地方:
public class Main {
public static void main(String[] args) {
int[] origin = {3,2,5,7,12,1,0};
// ISortStrategy sortStrategy = new InsertSort();
ISortStrategy sortStrategy = new QuickSort();
sortStrategy.sort(origin);
}
}
…
很简单,连图都可以不用放了。
扩展
就策略模式本身而言,确实没太多可说的。
还是来看一下一些在源码中的实现,比如Java的线程池中对拒绝任务的策略。我们知道,线程池有这么一个构造方法,其最后一个参数RejectedExecutionHandler就是选择对任务的拒绝策略:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
}
这个接口是这样的:
public interface RejectedExecutionHandler {
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
就一个方法。
一般情况下,这个是默认的AbortPolicy,也就是直接拒绝并抛出异常:
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
可以看下这个AbortPolicy的源码:
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
可以看到确实是直接抛出异常了。
另外还有DiscardPolicy、DiscardOldestPolicy、CallerRunsPolicy三种拒绝策略,分别代表着丢弃、丢弃任务队列运行最久的任务、尝试运行新添加的任务三种逻辑。
以上。