策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要交个人所得税,但是根据个人的收入情况,个人所得税的计算算法是有不同的策略的。
我想大家都看过《三国演义》,其中刘备娶孙夫人时,诸葛亮交给赵云三个
锦囊,就是三个策略
锦囊一:到达东吴,先去拜会乔国老锦囊二:刘备贪念美色不思离开,就对他谎称曹操大军压境锦囊三:如果被东吴军队追赶,求孙夫人解围
策略模式的UML类图如下:
主要角色分析:
Context是上下文,用一个ConcreteStrategy来配置,维护一个Strategy对象的引用;Strategy是策略类,用于定义所有支持算法的公共接口;ConcreteStrategy是具体策略类,封装了具体的算法或行为,继承于Strategy。
0x02:策略模式实现
Context:Context上下文角色,也叫Context封装角色,起承上启下的作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
//上下文接口
public void contextInterface() {
strategy.algorithmInterface();
}
}
Strategy:抽象策略角色,是对策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。algorithm是运算法则的意思。
public abstract class Strategy {
//算法方法
public abstract void algorithmInterface();
}
ConcreteStrategy:具体策略角色,用于实现抽象策略中的操作,即实现具体的算法,下方用print代替。
public class ConcreteStrategyA extends Strategy {
@Override
public void algorithmInterface() {
System.out.println("ConcreteStrategyA 实现");
}
}
public class ConcreteStrategyB extends Strategy {
@Override
public void algorithmInterface() {
System.out.println("ConcreteStrategyB 实现");
}
}
public class ConcreteStrategyC extends Strategy {
@Override
public void algorithmInterface() {
System.out.println("ConcreteStrategyC 实现");
}
}
策略模式测试代码:可以依次更换策略,测试一下策略模式。
public class Client{
public static void main(String[] args) {
Context context = null;
context = new Context(new ConcreteStrategyA());
context.contextInterface();
context = new Context(new ConcreteStrategyB());
context.contextInterface();
context = new Context(new ConcreteStrategyC());
context.contextInterface();
}
}
0x03:策略模式在JDK的运用
在多线程编程中,经常使用线程池来管理线程,以减缓线程频繁的创建和销毁带来的资源的浪费,其中ThreadPoolExecutor类中的RejectedExecutionHandler参数就是一个使用了策略模式的典型例子。
ThreadPoolExecutor的构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
RejectedExecutionHandler接口
public interface RejectedExecutionHandler {
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
RejectedExecutionHandler的四种策略实现
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
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());
}
}
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}