最近刚好在看设计模式,今天主要记录一下关于策略模式的使用方式
策略模式,英文名称叫Strategy Mode,我自己的理解就是通过实现不同的策略,来帮助我们的每个策略独立于它们的客户而变化,虽然这么不好解释,但是只要看了代码就明白了
其实要实现一个策略模式,基本分为下面三个类型:
- 策略类,用来定义我们要封装的策略
- 策略的实现类,用于实现不同的策略
- 策略的调用类,用来调用策略类
其实理解上面的一段话还是比较枯燥的,先看下面的例子吧,看完以后再回过头来看上面的这几点,就会理解的更加清晰一点了
例子:我们有3种算法,分别对应了3种不同的实现,但是我们在调用的时候,只会通过一种算法的code去判断我们要调用哪一种算法,我们的代码通常会怎么写?
首先定义出我们需要的3种算法类以及我们需要算法的code的枚举类:
public class Algorithm01 {
public void output(String name) {
System.out.println(name);
}
}
public class Algorithm02 {
public void output(String name) {
System.out.println(name);
}
}
public class Algorithm03 {
public void output(String name) {
System.out.println(name);
}
}
public enum AlgorithmType {
ONE(1),
TWO(2),
THREE(3);
int algorithmCode;
AlgorithmType(int algorithmCode) {
this.algorithmCode = algorithmCode;
}
AlgorithmType() {
}
// get、set方法略
}
然后在我们调用的时候,可以通过不同类型的code去调用我们需要的算法:
public static void main(String[] args) throws Exception {
// 这个地方只是举例子说明,假设每次只会有1种算法被调用
Random random = new Random();
int algorithmCode = random.nextInt(2) + 2;
if (algorithmCode == AlgorithmType.ONE.getAlgorithmCode()) {
Algorithm01 algorithm01 = new Algorithm01();
algorithm01.output("算法1");
} else if (algorithmCode == AlgorithmType.TWO.getAlgorithmCode()) {
Algorithm02 algorithm02 = new Algorithm02();
algorithm02.output("算法2");
} else if (algorithmCode == AlgorithmType.THREE.getAlgorithmCode()) {
Algorithm03 algorithm03 = new Algorithm03();
algorithm03.output("算法3");
} else {
throw new Exception("algorithm not found");
}
}
我们从上面的代码可以看出,当我们需要调用的时候,需要写好几个if-else来调用每一种不同的算法,那么这个时候,我们要怎么通过策略模式来优化我们的代码呢?
首先定义一个策略接口类:
public interface AlgorithmStrategy {
public void getAlgorithm(String param);
}
然后再定义我们的策略实现类,也就是3种不同类似的算法类,枚举类和上面的一致,在此处就不再重复了:
public class Algorithm01 implements AlgorithmStrategy {
@Override
public void getAlgorithm(String param) {
System.out.println(param);
}
}
public class Algorithm02 implements AlgorithmStrategy {
@Override
public void getAlgorithm(String param) {
System.out.println(param);
}
}
public class Algorithm03 implements AlgorithmStrategy {
@Override
public void getAlgorithm(String param) {
System.out.println(param);
}
}
下面编写我们的策略类的调用类:
public class StrategyCompute {
private static final Map<Integer, AlgorithmStrategy> algorithmMap = new HashMap<>();
static {
algorithmMap.put(1, new Algorithm01());
algorithmMap.put(2, new Algorithm02());
algorithmMap.put(3, new Algorithm03());
}
public AlgorithmStrategy getAlgorithm(int algorithmCode) throws Exception {
if (algorithmCode == -1) {
throw new Exception("algorithm not found");
}
return algorithmMap.getOrDefault(algorithmCode, null);
}
}
最后再补上我们调用某一种算法的主函数:
public static void main(String[] args) throws Exception {
Random random = new Random();
int algorithmCode = random.nextInt(2) + 2;
StrategyCompute compute = new StrategyCompute();
AlgorithmStrategy algorithmStrategy = compute.getAlgorithm(algorithmCode);
algorithmStrategy.getAlgorithm("算法" + algorithmCode);
}
可以看到,我们通过策略模式,将代码里面很多的if-else分支去掉了,既增加了代码的可读性,又减少了代码量
其实java源码里面也有用到策略模式的地方,最常见的就是ThreadPoolExecutor类,它里面处理异常策略的时候就用到了策略模式,我们知道线程池的异常策略有好几种,比如弃老策略,丢弃策略,中断策略等等,而这几种不同的异常策略,都是通过策略模式的方式去实现的