一、策略模式定义
策略模式定义比较简单,它的定义如下:
定义一组算法,将每个算法都封装起来,并且使它们之间可以互换(Define a family of algorithms,encapsulate each one,and make them interchangeable.)。
策略模式通用类图如下
按照上面类图,来实现一个简单的代码示例
策略类
public interface Strategy {
void algorithm();
}
具体策略类
@Slf4j
public class ConcreteStrategyA implements Strategy{
@Override
public void algorithm() {
log.info("ConcreteStrategyA");
}
}
@Slf4j
public class ConcreteStrategyB implements Strategy{
@Override
public void algorithm() {
log.info("ConcreteStrategyB");
}
}
Context类
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void algorithm() {
this.strategy.algorithm();
}
}
这里的Context类引入Strategy类的方式是通过构造方法的方式,也可以通过Setter的方式,或者直接不使用Strategy成员变量,而是使用Strategy对象作为方法参数传递进来。
启动类
public class Main {
public static void main(String[] args) {
Strategy strategy = new ConcreteStrategyA();
Context context = new Context(strategy);
context.algorithm();
}
}
可以看到,策略模式非常简单,没啥好说的,但是没觉得它眼熟吗?
二、策略模式和代理模式
策略模式的重点就是封装角色,它是借用了代理模式的思路,可以想想它和代理模式有什么差别,差别就是策略模式的封装角色和被封装的策略类不用是同一个接口,如果是同一个接口那就成为了代理模式。
代理模式的类图
Proxy类如果没有实现Subject类,那就变成了策略模式。
三、扩展篇:策略枚举
这里借助一个加减法的例子来递进说明下策略枚举:输入三个参数,进行加减法运算参数中两个是int型的,剩下的一个参数是String型的,只有“+”、“-”两个符号可以选择,表示两个参数进行加法或者减法运算,输出运算结果。
方式一:不使用策略模式
非常简单,直接编程实现
public class Calculator {
//加符号
private final static String ADD_SYMBOL = "+";
//减符号
private final static String SUB_SYMBOL = "-";
public int exec(int a, int b, String symbol) {
int result = 0;
if (symbol.equals(ADD_SYMBOL)) {
result = this.add(a, b);
} else if (symbol.equals(SUB_SYMBOL)) {
result = this.sub(a, b);
}
return result;
}
//加法运算
private int add(int a, int b) {
return a + b;
}
//减法运算
private int sub(int a, int b) {
return a - b;
}
}
方式二:使用策略模式
Calculator接口
public interface Calculator {
int exec(int a, int b);
}
家减法Caculator实现
public class AddCalculator implements Calculator {
@Override
public int exec(int a, int b) {
return a + b;
}
}
public class SubCalculator implements Calculator {
@Override
public int exec(int a, int b) {
return a - b;
}
}
Context类
public class Context {
private Calculator calculator;
public Context(Calculator calculator) {
this.calculator = calculator;
}
public int exec(int a, int b) {
return this.calculator.exec(a, b);
}
}
启动类
public class Main {
public static void main(String[] args) {
String ope = "+";
int a = 1;
int b = 2;
Context context = null;
switch (ope) {
case "+":
context = new Context(new AddCalculator());
break;
case "-":
context = new Context(new SubCalculator());
break;
default:
break;
}
int exec = context.exec(a, b);
System.out.println(exec);
}
}
方式三:策略枚举
来直接看下策略枚举的实现方式
策略枚举类
public enum Calculator {
//加法
ADD("+") {
@Override
int exec(int a, int b) {
return a + b;
}
},
SUB("-") {
@Override
int exec(int a, int b) {
return a - b;
}
};
Calculator(String ope) {
this.ope = ope;
}
String ope;
abstract int exec(int a, int b);
public static Calculator get(String ope) {
return Arrays.stream(Calculator.values())
.filter(item -> item.ope.equals(ope))
.findFirst()
.orElse(null);
}
}
启动类
public class Main {
public static void main(String[] args) {
int a = 1;
int b = 2;
String ope = "+";
int result = Calculator.get(ope).exec(a, b);
System.out.println(result);
}
}
策略枚举是一个非常优秀和方便的模式,但是它受枚举类型的限制,每个枚举项都是public、final、static的,扩展性受到了一定的约束,因此在系统开发中,策略枚举一般担当不经常发生变化的角色。
END.
注意:本文归作者所有,未经作者允许,不得转载