说明

Strategy模式也称为“策略模式”。该模式将某些关键的算法从实现类中解耦,让调用者可以选择不同的算法灵活地应用于实现类。

模式类图

根据设计模式,Strategy模式的UML图如下:

Strategy模式

该类图中几个关键概念:

Context:实现类,如果没有使用策略模式,那么Strategy中的算法应该被包含在Context内;
Strategy:策略接口,提供算法接口,Context使用接口调用具体的策略算法;
ConcreteStrategy:策略实现类,实现策略接口中的方法

策略说明

优点

  • 将数据(Context)和算法(Strategy)解耦,算法可以灵活地演化而不必修改数据操作相关代码,反之亦然。
  • 消除代码中可能出现的大量if else

不足

  • 调用者需要了解ConcreteStrategy的实现细节,以便可以在多种ConcreteStrategy中作出合适选择。

实现细节

实际上,无法将Strategy与Context做到完全解耦,因为Strategy实现时或多或少需要使用Context的数据,有以下几种方案实现Strategy对Context的数据访问

  • Context调用Strategy接口时,通过参数传递,这样可尽量解耦
  • Strategy内部记录Context的引用,Strategy需要时直接调用Context方法访问数据。

JDK示例

Strategy模式

ThreadPoolExecutor的4中线程池拒绝策略,也可以自定义实现RejectedExecutionHandler进行扩展

  • AbortPolicy:无法处理任务任务的时候,直接抛出异常,
  • DiscardPolicy: 丢弃当前将要加入队列的任务本身
  • DiscardOldestPolicy: 丢弃任务队列中最旧任务
  • CallerRunsPolicy: 由调用者线程去执行,在任务提交速度过快的情况,可减少任务提交的速度,同时可以保证任务的执行。
// Strategy
public interface RejectedExecutionHandler {

    /**
     * Method that may be invoked by a ThreadPoolExecutor when ThreadPoolExecutor cannot accept a task.
     */
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

// Context
public class ThreadPoolExecutor extends AbstractExecutorService {
        ......
        private volatile RejectedExecutionHandler handler;
        ......
}

// Concrete Strategy
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        public DiscardOldestPolicy() { }
        // implement rejectedExecution
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

参考