减少if else
代码是死的,人是活的。具体怎么使用还得看具体的场景。这里只是抛砖引玉。
策略模式
策略模式,不用多说,直接代码:
- 定义一个策略接口:
public interface Strategy {
/**
* 具体的策略,做某个事情
*
* @author FYK
*/
void doSomething();
}
- 具体的策略类:
public class StrategyA implements Strategy {
@Override
public void doSomething() {
System.out.println("策略A AAAAAAAAAAAAA");
}
}
public class StrategyB implements Strategy {
@Override
public void doSomething() {
System.out.println("策略B BBBBBBBBB");
}
}
public class StrategyC implements Strategy {
@Override
public void doSomething() {
System.out.println("策略C CCCCCCCCC");
}
}
- 策略上下文调用策略:
public class StrategyContext {
@Setter
private Strategy strategy;
/**
* 执行策略
*
* @author FYK
*/
public void doStrategy() {
strategy.doSomething();
}
}
使用策略模式
完成以上代码之后,策略模式算是完成了。当初也就是学到这里,代码完全明白,但是用的时候懵逼,这里给出一个大多数使用策略模式的方式:
public class StrategyContextTest {
@org.junit.Test
public void doStrategy() {
StrategyContext context = new StrategyContext();
// 使用策略A
context.setStrategy(new StrategyA());
context.doStrategy();
// 使用策略B
context.setStrategy(new StrategyB());
context.doStrategy();
// 使用策略C
context.setStrategy(new StrategyC());
context.doStrategy();
}
}
问题
以上,使用策略模式中,有一个问题:当要使用策略A的时候,是具体的传入了一个StrategyA的实例。这个在实际使用的时候,很难做到(这要求使用者清楚每个策略的实现类是做什么的,以及如何构造实例类)。更主要的是:通常情况下有很多策略类,具体需要哪个策略类,是需要一个参数来判断的。所以,常见的代码是配合工厂模式,通过一个标识符来判断该创建那个策略类:
if(flag = A){
return A;
}else if(flag = B){
return B
}else if(flag = C){
return C
}
因此,每增加一个策略类,就需要修改这个工厂方法中的if else代码。if else代码多了之后,照成的问题,懂的人都懂,以下介绍解决这些if esle的一些方法。
减少if else:枚举法
枚举中,可以定义一个方法。
如下:将所有的策略都定义在一个枚举类中(是情况而定)
public enum StrategyEnum {
StrategyA {
@Override
void doSomething() {
System.out.println("策略A AAAAAAAAAAAAA");
}
},
StrategyB {
@Override
void doSomething() {
System.out.println("策略B BBBBBBBBBBBBB");
}
},
StrategyC {
@Override
void doSomething() {
System.out.println("策略C CCCCCCCCCCCCC");
}
};
abstract void doSomething();
}
然后策略上下文:
@UtilityClass
public class StrategyContext {
public void deStrategyEnum(String strategyFlag){
StrategyEnum strategyEnum = StrategyEnum.valueOf(strategyFlag);
strategyEnum.doSomething();
}
}
这样,只需要传入在枚举中定义的策略类的名字就可以了:
public class StrategyContextTest {
@Test
public void deStrategyEnum() {
StrategyContext.deStrategyEnum("StrategyA");
}
}
通常而言,策略标识,是由调用方(例如前端或者配置文件)传入的,这样,如果需要增加某个策略,就只需要在策略枚举中加入策略实现即可,无需其他操作了。
减少if else:享元模式
享元模式来实现这个减少if else很简单:这里说下原理,代码就不全写了。
享元模式的基本格式:
public class StrategyFactory {
private Map<String, Strategy> strategyManager = new ConcurrentHashMap<>();
public Strategy getStrategy(String strategyFlag){
//一般而言,策略Strategy 实现类,都是放在一个包下的(或者是有一定的规律的地方,这样也便于以后查找所有的策略类代码),既然是放在一个包下,那么就可以通过一个扫描工具类,加载出所有的策略类实现。
Strategy strategy = strategyManager.get(strategyFlag);
if(strategy== null){
//扫描策略类,放入map中
strategyManager .put(strategyFlag, strategy);
}
return strategy;
}
}
所以,简单的说,就是利用享元模式,将所有的策略以key-value的形式放入一个map中,然后在使用的时候,通过key,在map中使用get方法就可以获得具体的策略了,这样也减少了if else的使用。
总结
以上方式,是我目前了解到了可以减少if else的使用方法,这里只是用策略模式来举例,并不是单单只能再这里使用,后续有发现更好的方式再继续更新。
另外,这些个方法各有各的好处,具体的是使用还得看个人。顺便说下:并不是出现多个if else的地方就需要优化,要看具体的业务场景,有时候多个if else代码或许会让代码更加清晰。