在平时开发中,有时避免不了使用大量判断,简单处理的话就使用if...else...了,但过多层的if else对于性能有很大的开销,而且业务复杂的话,耦合太重,对于后期的拓展也不是很友好,所以使用策略模式。
1. 策略+工厂实现相同业务抽象
策略模式:一种解耦的方法,它对算法进行封装,使得算法的调用和算法本身分离。使用策略模式客户端代码不需要调整,算法之间可以互相替换,因为不同的算法实现的是同一个接口。策略模式是一种对象行为型模式。策略模式符合“开闭原则”。
策略模式包括如下角色:
- Context :环境类
- Strategy:抽象策略类
- ConcreteStrategy:具体策略类
下面简单抽象下业务逻辑:
String name = "shaqiang";
if(name.equals("saobin")){
System.out.println("I am SaoBin");
}else if(name.equals("shaqiang")){
System.out.println("I am ShaQiang");
}else if(name.equals("weifeng")){
System.out.println("I am WeiFeng");
}
有成员“骚斌”、“傻强”、“伟峰”···,其执行逻辑基本一样,基于策略模式对其进行改造:
1.1 定义策略接口
将成员的业务方法抽象为统一的策略接口。其中 InitializingBean 接口来自Spring框架,用于实现环境的统一工厂。
import org.springframework.beans.factory.InitializingBean;
/**
* 策略总接口*/
public interface NameHandler extends InitializingBean {
/**
* 输出名称
* @param name
*/
public void myName(String name);
}
1.2 实现策略工厂
此处的工厂即策略模式下的 “环境类” 要素,功能为根据不同的name找到其对应的不同的策略实现,实现方法为将实现NameHandler接口的类都装载到strategyMap里,除使用工厂实现外,也可以使用枚举+代理实现。
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* 工厂设计模式*/
public class NameSetFactory {
private static Map<String, NameHandler> strategyMap = new HashMap<>();
/**
* 根据name获取对应的handler实现
* @param name
* @return
*/
public static NameHandler getInvokeStrategyMap(String name){
return strategyMap.get(name);
}
/**
* 注册
* @param name
* @param handler
*/
public static void register(String name, NameHandler handler){
if(StringUtils.isEmpty(name)||null == handler){
return;
}
strategyMap.put(name,handler);
}
}
1.3 为各成员实现各自的具体策略实现类
将各自实现类声明为组件(用于维护工厂),org.springframework.beans.factory.InitializingBean#afterPropertiesSet内部实现工厂注册。
import org.springframework.stereotype.Component;
/**
* saobin策略实现*/
@Component
public class SaoBinHandler implements NameHandler {
/**
* 输出名称
* @param name
*/
@Override
public void myName(String name) {
System.out.println("I am SaoBin");
}
@Override
public void afterPropertiesSet() throws Exception {
NameSetFactory.register("saobin",this);
}
}
import org.springframework.stereotype.Component;
/**
* shaqiang策略实现*/
@Component
public class ShaQiangHandler implements NameHandler {
/**
* 输出名称
* @param name
*/
@Override
public void myName(String name) {
System.out.println("I am ShaQiang");
}
@Override
public void afterPropertiesSet() throws Exception {
NameSetFactory.register("shaqiang",this);
}
}
import org.springframework.stereotype.Component;
/**
* weifeng策略实现*/
@Component
public class WeiFengHandler implements NameHandler {
/**
* 输出名称
* @param name
*/
@Override
public void myName(String name) {
System.out.println("I am WeiFeng");
}
@Override
public void afterPropertiesSet() throws Exception {
NameSetFactory.register("weifeng",this);
}
}
1.4 新增if逻辑拓展
如上,如果后续再加新成员的业务,只需要实现其对应的具体策略类即可,不需要关注其对其他成员的业务是否有影响。
2. 策略模式+工厂模式+模板模式实现不同业务
现在来了新需求,之前成员实现的方法基本一致,但现在要求:“骚斌”实现打印名称,“傻强”实现跳舞,“伟峰”实现打印名称和跳舞,后续随时会有新增成员和新增功能,基于上面的实现,可以在策略总接口中新增跳舞方法,实现如下:
可以看出,在总策略接口中新增“跳舞”方法后,没有该功能的“骚斌”也需要实现它,这个就很不友好了。下面对其进行改造:
2.1 模板设计模式改造总策略接口
将原先的接口改造为抽象类,实现模板模式,所有的功能在类中定义,子类要实现具体功能,重写即可。
import org.springframework.beans.factory.InitializingBean;
/**
* 策略抽象类(模板)
*/
public abstract class AbstractNameHandler implements InitializingBean {
/**
* 输出名称
* @param name
*/
public void myName(String name){
throw new UnsupportedOperationException();
};
/**
* 跳舞
* @param name
*/
public void dance(String name){
throw new UnsupportedOperationException();
};
}
2.2 策略实现
各成员只需实现其对应的策略方法即可。
如下,测试成员功能,对于有具体实现的方法,成员会执行,如果没有具体实现,会抛出异常。
经过上面改造,后面如果新增成员或者新功能实现,新增策略实现即可。这种改造符合开闭原则,适用较为复杂的逻辑判断。
————————————————