策略模式配合枚举类
在项目中碰到一个根据循环类型(天、周、月等)获取一个时间偏移量的问题。一开始我的想法是通过ifelse判断类型,但这样就会有多层的if判断。
public void demo(){
Integer type = A.getType();
if(type == Type.DAY.getCode()){
...
}
if(type == Type.DAY.getCode()){
...
}
...
}
public enum Type{
DAY(1,"天"),
WEEK(2,"周"),
...
;
private final Integer code;
private final String info;
...
}
多层的if,让我突然想起来前几天看到阿里巴巴Java开发手册中有一句话
那么就使用策略模式来试着优化一下吧!
策略模式
首先我们需要一个抽象策略接口
//抽象策略接口
public interface IStrategy{
void function();
}
然后,我们需要让他实现不同的实体类
// 例如 这个AAA策略
public class AAAStrategy implements IStrategy{
@Override
public void function(){
System.out.println("这里是AAA策略实现类...");
}
}
// BBB策略
public class BBBStrategy implements IStrategy{
@Override
public void function(){
System.out.println("这里是BBB策略实现类...");
}
}
接下来,我们还需要一个可以让我们控制使用哪种策略的控制类
public class StrategyHandler{
//定义一个内部属性为 抽象策略接口
private IStrategy iStrategy;
//实现一个set方法 让我们能够指定选择策略
public void setIStrategy(IStrategy iStrategy){
this.iStrategy = iStrategy;
}
//统一策略方法入口
public void strategyFunction(){
iStrategy.function();
}
}
到这里我们的策略方法就写完啦,那么如何使用呢?
其实很简单,看代码
public void demo(){
//得到handle控制类
StrategyHandle handle = new StrategyHandle();
//指定策略方法
handle.setIStrategy(new AAAStrategy());
//使用统一策略方法入口
handle.strategyFunction();
}
这样我们的策略模式也就实现了,但是回过头看看实际项目需求,我突然发现对于设置策略方法他还是需要一段段的if去判断(怎么会这样.jpg)
就像这样
public void demo(){
Integer type = 实现类.getType();
//得到handle控制类
StrategyHandle handle = new StrategyHandle();
//指定策略方法
if(type == 1){
//指定A策略
}
if(type == 2){
//指定B策略
}
...
}
阿巴阿巴阿巴,我到底写了个什么。
配合枚举
之后呢,思考了一会该怎么避免,我突然想到为什么我不把策略放到枚举类中
//像这样
public enum Type{
A(1,new AAAStrategy),
B(2,new BBBStrategy);
private final Integer code;
private final IStrategy iStrategy;
//这里有一个getIStrategy方法
public IStrategy getIStrategy(){
...
}
//这里有一个 根据code 获得对于Strategy方法
public static ICycleStrategy getStrategyByCode(Integer code){
}
}
那么之前的结果就变成了
public void demo(){
Integer type = 实现类.getType();
//得到handle控制类
StrategyHandle handle = new StrategyHandle();
//获取对应策略
IStrategy iStrategy = Type.getStrategyByCode(type);
//指定策略方法
handle.setIStrategy(iStrategy)
//方法入口
...
}
完美!
感谢导师提醒,突然发现如果把具体的实现类放入枚举类的属性当中,那么handler大概就不需要了 最后的结果就是直接获取枚举当中策略然后执行方法
//像这样
public void demo(){
Integer type = 实现类.getType();
//获取对应策略
IStrategy iStrategy = Type.getStrategyByCode(type);
//方法入口
iStrategy.function();
...
}
总结
我尝试在枚举类中放入对于的实现策略,这样就可以通过数据库的值变化,来变换不同的策略。
那么增加和删除对业务代码也不会做改动,只需要实现或者删除一个策略实现类,再增加一个枚举就可以了。
进一步优化的想法
这些天看了一些文章,对于进一步的优化有了新的想法:
- 优化策略模式带来的策略类的增加 -> 内部类 -> 匿名内部类
- 对于大量策略的增加 内部类依旧不吃好 -> 加入函数式接口以及lamda表达式
- 对于其他类型的扩展 -> 优化为泛型