继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

从if else到解耦

xpbob
关注TA
已关注
手记 152
粉丝 1.6万
获赞 380

我们在写一段复杂的条件判断的时候if,switch算是常用手段了。随着逻辑的复杂,如果if嵌套5层,相信代码的可读性已经是比较差了,需要在整个方法上加注解来说明为什么这么写,这已经不是一个人容易摸索出来的情况了。
我们想象一下如何继续在这样的代码上继续迭代,首先得写好自己的新增逻辑,然后再控制器的类上加上if判定。如果一直新增,或者条件修改,那么控制类一定要跟着变。这样的情况明显是违背开闭原则的。增加或者修改都得修改控制类。

改良1 配置文件

造成上面必须修改控制类的一个重要原因是if这样的逻辑是硬编码到代码的。这样的过程其实是可以抽取成为配置文件的。
文件的修改是方便的,起码是不用再次编译代码了。已经达到一定程度的对扩展开放了,例如过滤器。
但是这种情况一般是对外提供的服务使用的方式,如果是一个项目,这个真没有硬编码来的实在,ide有扫描类的功能,可以发现哪些类没有被使用,写配置文件的方式就很容易忽略掉配置这个步骤。

改良2 再次抽象

我们写的if else代码。其实每次都要写实现过程以及如果判断能这么实现的方式或者标志。
以简单工厂模式为例,如果我们想实现一个创建操作实体类的工厂,我们的代码基本是下面这么写的

    public static Operation createOperation(String demo) {
        switch (demo) {
            case "A":
                operationObj = A();
                break;
            case "B":
                operationObj = B();
                break;
        }
        return operationObj;
        }

我们使用的是java编码,我们可以利用java的特性来缩减上面的过程

Class.forName(demo).newInstance()

这里使用了java的一个特性,就是通过class对象创建实例,我们是如何省去选择语句的逻辑的呢?
靠约束。这里定义了类名必须是和传入参数一样的名字。如果说if else是线性查找,及他是一个一个从开头一直找到合适的。那么上面的方式,我们采取的就是散列的模式,直接定位。

对比

我们通过上面的两个案例,来对比一下(下面称线性模式,散列模式)。线性模式的特点是可读性强,都有明确的判定,这个到底是什么情况进入。散列模式因为加了抽象,作为了更通用的模式,他阅读起来相对不友好,需要很多注释和约束来控制,否则就会出现大家看着逻辑莫名其妙的情况。散列模式定位更快,线性模式随着判断阅读会越来慢,可能if判定了20次都没到具体的判断上。散列模式如何描述规范是个很大的问题,尤其是规范可能是不好描述的。举个例子,我们真实的场景不单单是创建个对象,可能if判断是创建什么对象,调用什么方法。这个才是我们真是需要的。我们举的例子明显不满足这种情况。

下面就说一种最佳实践

当注解遇到spring

java中的注解,我们在spring中用的特别多,但是自定义注解的情况,相对用的少。下面就通过自定义注解,达到解耦的目的。
首先构建自己的注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Executor {
	int exec();
}

把注解加入到具体的逻辑代码中

public interface Handler {
	@Executor(exec= 1)
	public void showInfo();
}	

具体的实现类就通过spring注解,让spring扫描到。
最后我们要做的就是维护判定关系。

@Component
public class Processor implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

		Class<? extends Object> clazz = bean.getClass();
		
		//获取方法上的注解维护一个结构
			...
		
	}

}

这里利用了spring构建类的功能,并且可以拿到对应的类,从中获取到方法的注解。自己组织一个map用来保存。

总结

从上面的逻辑上,我们可以看出,我们思维上判定的逻辑一个没少,通过解耦只是做到了扩展的时候写更少的代码,记住,是扩展的时候。有些情况扩展需要不大,if else大可以舒舒服服的用,这个需要开发者对业务有个比较好的把握。

打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP