赞
踩
java中用策略模式替代if-else的大段逻辑
java本来是一门以面向对象为主的语言,但很多人嘴上说着java面向对象,然后除了表映射实体之外,其他的还是面向过程的思路。
就比如今天要说的,代码中大段大段的if-else判断,每个if-else代码块中又有很多复杂的逻辑,导致整个代码混乱不堪,让别人看到就感觉看到屎一样的代码一样。
那么,如何优雅的替代这些代码呢,其实有个设计模式(策略模式)就很好的解决了这个问题。
比如说订单处理,订单会有多个type状态,比如说
type=1的时候,就执行普通订单的逻辑;
type=2的时候,就执行满减促销订单的逻辑;
type=3的时候,就执行满返促销订单的逻辑;
等等,可能type会有数十种甚至更多种情况。
然后有些人就会开始if-else了,比如有如下的伪代码:
if(type=1){
普通订单...(此处省略100多行处理逻辑)
}else if(type=2){
满减促销订单...(此处省略100多行处理逻辑)
}else if(type=3){
满返促销订单...(此处省略100多行处理逻辑)
}else if(type=n){
...(此处省略几百上千行的逻辑)
}
做的好点的,会把if-else代码块中的逻辑,抽成一个个的方法,会稍微显的代码清晰许多,但这些都是面向过程的思想。
我认为,这种情况就应该用以下这种方式,即,用策略模式代替if-else,真正做到面向对象。
把每种不同类型的订单抽成一个个对象,然后通过不同的注解标识来区分调用。
首先,本次例子用的是Spring-Boot框架,亲测没问题。SpringMVC框架应该也是没问题的。
定义一个订单类,里面有type属性,type可以是"1"、“2”、“3”…
定义一个抽象类AbstractHandler,里面有个抽象方法handle,入参是订单类
定义一个注解HandlerType,有个value属性,value是几就代表这个注解注的这个类是什么类型的订单
定义普通类HandlerImpl01,实现AbstractHandler,代表普通订单,即@HandlerType(“1”);
定义普通类HandlerImpl02,实现AbstractHandler,代表满减促销订单,即@HandlerType(“2”);
定义普通类HandlerImpl03,实现AbstractHandler,代表满返促销订单,即@HandlerType(“3”);
定义一个初始化类HandlerProcessor,实现BeanFactoryPostProcessor,过程如下:
1、找到带有注解@HandlerType的类,
2、以注解的值为key,对应的类为value,存在一个map中
3、将这个map作为构造函数的参数,初始化HandlerContext,将HandlerContext注册到spring中成为一个单例bean。
很明显,目的就是为了保存不同type对应的不同类。
定义类HandlerContext,有个map类型的属性叫handlerMap,有个getInstance的方法,入参是type,返回AbstractHandler。
最后使用的时候,是先调用handlerContext.getInstance方法,根据type获取对应的AbstractHandler。
然后再调用他的handle方法,执行对应订单类型的处理逻辑。
//@Data是lombok的注解,为了省略不写get/set方法
@Data
public class OrderDTO {
private String code;
private BigDecimal price;
/**
* 订单类型
* 1:普通订单
* 2:满减订单
* 3:满返订单
*/
private String type;
}
public abstract class AbstractHandler {
abstract public String handle(OrderDTO orderDTO);
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface HandlerType {
String value();
}
@Component
@HandlerType("1")
public class HandlerImpl01 extends AbstractHandler {
@Override
public String handle(OrderDTO orderDTO) {
System.out.println("处理type为1的订单,orderDTO.type="+orderDTO.getType());
return "success";
}
}
@Component
@HandlerType("2")
public class HandlerImpl02 extends AbstractHandler {
@Override
public String handle(OrderDTO orderDTO) {
System.out.println("处理type为2的订单,orderDTO.type="+orderDTO.getType());
return "success";
}
}
@Component
@HandlerType("3")
public class HandlerImpl03 extends AbstractHandler {
@Override
public String handle(OrderDTO orderDTO) {
System.out.println("处理type为3的订单,orderDTO.type="+orderDTO.getType());
return "success";
}
}
@Component @SuppressWarnings("unchecked") public class HandlerProcessor implements BeanFactoryPostProcessor { //这里是具体的handler策略类的包的位置,为了后面的包扫描 private static final String HANDLER_PACKAGE = "com.zs.handler"; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { Map<String, Class> handlerMap = new HashMap<>(); //包扫描 ClassScaner.scan(HANDLER_PACKAGE,HandlerType.class).forEach(clazz ->{ Annotation annotation = clazz.getAnnotation(HandlerType.class); HandlerType handlerType = (HandlerType) annotation; String type = handlerType.value(); System.out.println(type); handlerMap.put(type,clazz); }); HandlerContext handlerContext = new HandlerContext(handlerMap); //注册单例 beanFactory.registerSingleton(HandlerContext.class.getName(),handlerContext); } }
public class HandlerContext {
private Map<String,Class> handlerMap;
public HandlerContext(Map<String, Class> handlerMap) {
this.handlerMap = handlerMap;
}
public AbstractHandler getInstance(String type){
Class clazz = handlerMap.get(type);
if(clazz == null){
throw new IllegalArgumentException("没有type对应的处理器,type:"+type);
}
return (AbstractHandler)SpringContextUtils.getBean(clazz);
}
}
定义接口:
public interface OrderService {
/**
* 根据订单类型处理订单
* @param orderDTO
* @return
*/
String handle(OrderDTO orderDTO);
}
实现接口:
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private HandlerContext handlerContext;
@Override
public String handle(OrderDTO orderDTO) {
System.out.println("OrderServiceImpl handle 方法开始执行===");
AbstractHandler handler = handlerContext.getInstance(orderDTO.getType());
return handler.handle(orderDTO);
}
}
包扫描的工具类:
public class ClassScaner implements ResourceLoaderAware { private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); private final List<TypeFilter> includeFilters = new LinkedList<TypeFilter>(); private final List<TypeFilter> excludeFilters = new LinkedList<TypeFilter>(); private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); public ClassScaner() { } public void setResourceLoader(ResourceLoader resourceLoader) { this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader); this.metadataReaderFactory = new CachingMetadataReaderFactory( resourceLoader); } // public final ResourceLoader getResourceLoader() { // return this.resourcePatternResolver; // } public void addIncludeFilter(TypeFilter includeFilter) { this.includeFilters.add(includeFilter); } // public void addExcludeFilter(TypeFilter excludeFilter) { // this.excludeFilters.add(0, excludeFilter); // } // public void resetFilters(boolean useDefaultFilters) { // this.includeFilters.clear(); // this.excludeFilters.clear(); // } public static Set<Class> scan(String basePackage, Class<? extends Annotation>... annotations) { ClassScaner cs = new ClassScaner(); for (Class anno : annotations) cs.addIncludeFilter(new AnnotationTypeFilter(anno)); return cs.doScan(basePackage); } // public static Set<Class> scan(String[] basePackages, Class<? extends Annotation>... annotations) { // ClassScaner cs = new ClassScaner(); // for (Class anno : annotations) // cs.addIncludeFilter(new AnnotationTypeFilter(anno)); // Set<Class> classes = new HashSet<Class>(); // for (String s : basePackages) // classes.addAll(cs.doScan(s)); // return classes; // } public Set<Class> doScan(String basePackage) { Set<Class> classes = new HashSet<Class>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + org.springframework.util.ClassUtils .convertClassNameToResourcePath(SystemPropertyUtils .resolvePlaceholders(basePackage)) + "/**/*.class"; Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); for (int i = 0; i < resources.length; i++) { Resource resource = resources[i]; if (resource.isReadable()) { MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); if ((includeFilters.size() == 0 && excludeFilters.size() == 0) || matches(metadataReader)) { try { classes.add(Class.forName(metadataReader.getClassMetadata().getClassName())); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } } catch (IOException ex) { throw new BeanDefinitionStoreException( "I/O failure during classpath scanning", ex); } return classes; } protected boolean matches(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return false; } } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return true; } } return false; } }
spring工具类,为了获取bean
@Component public class SpringContextUtils implements ApplicationContextAware { private static ApplicationContext applicationContext = null; public static ApplicationContext getApplicationContext(){ return applicationContext; } @SuppressWarnings("unchecked") public static <T> T getBean(String beanId) { return (T) applicationContext.getBean(beanId); } public static <T> T getBean(Class<T> requiredType) { return (T) applicationContext.getBean(requiredType); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextUtils.applicationContext = applicationContext; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。