if else太多用什么设计模式,if else紧凑形式
面向过程设计和面向对象设计的主要区别是在业务逻辑层是否使用冗长的if else判断。如果你还在大量使用ielse,当然除了接口表示层,即使你使用的是Java/C#这样完全面向对象的语言,也只能说明你的思维还停留在传统的面向过程的语言上。传统思维习惯分析
为什么要在业务逻辑层使用雅思?其实用户的目的是复用,但这是对工艺编程的复用。程序员只看到代码复用,因为他看到的是雅思大部分代码在几种情况下是重复的,只有少数是不同的。所以用雅思可以避免代码重复,他认为是模板模式。
范的错误在于程序员只从代码运行顺序的方向来看代码。这种思维类似于水管或者串联电路。水沿着水管流动(代码运行顺序),当遇到几个分支(子管道)时,就被赋给这些流动的分支,相当于代码的if else。
使用OO时,首先打破了代码自顶向下的顺序等于运行时顺序的规律。代码结构不是由执行顺序决定的,而是由什么决定的?OO设计的;设计模式会取代这些iElse,但最终,Service之类的通用类总是按照运行顺序组装这些OO模块。在EJB,只有一个地方可以包含事务(通常是服务)和会话bean。
一旦需求发生变化,我们更有可能成为服务中的每个OO模块,甚至只是改变服务中OO模块的执行顺序来满足需求。
在这里,我们也看到了OO分离的思想,将以前过程化语言的一个主要功能完全分解,将运行序列与代码的其他逻辑分离开来,而不是像面向过程那样混淆。所以有人觉得OO也是有顺序的,这是肯定的。关键是跑单要分开。
有没有if else可以看出你有没有把跑单拆分到你家。
设计模式的入口点
经常有人说设计模式好,但是我很难用。实际上,如果你用ielse写代码(除了显示控制),你就是在写业务逻辑,只是用简单的判断语句代替真实情况。
我们以大家熟悉的论坛帖子为例。比如ForumMessage就是一个模型,但在实际操作中,帖子分为两种:主题帖(第一个根帖)和回复帖(回以前帖子的帖子)。这里有一个简单的解决方案:
建立一个ForumMessage,然后在ForumMessage中添加类似isTopic的判断语句。注意,在这里引入一个简单的属性判断可能会导致在程序的其他部分到处都是if else判断。
如果换一种分析和实现思路,用对象化的概念来看,其实有两种对象,即主题帖和回复帖,但这两种对象大部分是一致的,所以我设置ForumMessage为主题帖;然后创建ForumMessage的子类ForumMessageReply作为回复。这样,我在一个程序的地方,比如Service,我已经确定这个模型是一个回复,所以我可以直接下载为ForumMessageReply。这有点类似于将对象放入集合或从集合中取出时的强制类型转换。通过这种手段,我在以后的程序中排除了if else判断语句的可能性。
这说明如果分析方向不对,也会导致模式误用。
例如,我们不能在没有业务上下文场景的情况下讨论设计模式,否则我们无法决定是否使用模式。这里有两个对比例子:
首先,本文中举例说明的第一个代码案例没有上下文,文本中只陈述了一段代码:
main() { if(情况A){
//使用策略A
}否则(情况B){
//使用策略B
}否则(情况C){
//使用策略C
}
}
这个代码是纯代码,没有业务功能。所以,在这种情况下,我们很难确定使用哪种模式,即必须使用策略模式等。而我们也逃脱不了还在用雅思的命运。设计模式不是魔术,也不能让一段没有意义的代码变得简单,只能让它体现的业务功能更容易扩展。
其次,在这篇文章中,作者引用了PacketParser的一个商业案例。此代码反映了业务功能,是一个数据包分析。作者还比较了各种模式的不同用法,所以我们还是用动态代理模式或者命令模式来排除那些可能存在的if else。
以上两个案例说明,业务逻辑是我们使用设计模式的出发点,在分解业务逻辑时,我们习惯使用ielse来实现。当你有这个意图或者已经实现了代码,就要考虑是否需要重构重构。
否则替换
那么在实战中,有哪些设计模式可以替代if else?其实可以用GoF设计模式代替if else,我们描述如下:
状态模式
当数据对象有各种可能的状态,并且这种状态会影响不同的业务结果时,那么就要考虑是否使用状态模式。当然,在使用状态模式之前,你首先要有内存状态的概念,而不是数据库,因为在传统的面向流程/面向数据库的系统中,你很难找到状态,从数据库中读取某个值,然后根据这个值分配代码。这是很多新手经常做的事情。参考文献:状态对象:数据库的替代品
也有使用传统语言思维的情况:使用类整数变量来标识状态:公共类顺序{
私有int状态;
//描述:
//status=1表示订购但查看;
//status=2表示已经查看过未处理的;
//status=3表示未付款已经处理。
//status=4表示已经付款但是货物还没有发货。
//status=5表示货物已经交付。
}
上面的类设计无疑是将类作为传统语言的函数,这就导致了程序代码中大量的if else。
策略模式
当你面临几种算法或公式的选择时,可以考虑策略模式。传统流程语言情况下,算法值从数据库中读取,值1表示策略1,比如保存到数据库;值2表示策略2,例如保存到XMl文件。这里,if else用作策略选择的开关。
命令模式
流程的传统思维情况是:如果客户端发出一个代号1或者‘a’,那么我调用对象A.java来处理;如果代码名是2或者‘b’,我就调用B.java来处理,通过if else判断客户端发来的代码,然后根据事先约定的对应表调用相应的类来处理。
MVC模式
MVC模式的传统语言误用类似于命令模式。在动作类中,if else用于前台和后台调度。如果客户端发送任何命令;我会调用后台什么结果;如果你在后台处理什么结构,再决定推什么页面。但是,现在我们用Struts/JSF作为MVC模式的框架实现者,就不用犯这种低级错误了。
责任链模型
责任链模式和命令模式可选,如果真的不知道客户端会发出什么代码;没有预定义的对照表,只能写一个类打开这个包看看。与Command不同,它是在AOP vs Decorator中分析的。
或动态代理模式。
代理可以是满足特定条件的代表,例如,权限检查。传统的面向过程的思维是:当一个用户登录并访问一个资源时,它使用ielse进行判断。只有满足某些条件,才能允许访问。这样权限判断和业务数据逻辑就混淆了,代理模式也就可以清晰地区分了。如果太差,就用动态代理或者下面的AOP。
AOP或装饰模式
实际上,在我们的业务中,使用过滤器也可以替代if else。过滤器起到过滤筛选的作用,拦截符合这个过滤器条件的对象去做某件事。这是一个过滤器的作用,多个过滤器的组合其实就是if else的组合。
所以,如果实在想不出什么办法,可以用滤镜。最好将过滤器理解为防火墙。当客户端有请求时,会穿过不同性质的防火墙,防火墙会拦截端端口;那个防火墙就是安全检查,拦截等等。滤镜也像红、蓝、白光滤镜;红色滤光片只能拦截通过光中的红色;蓝色滤镜截取光线中的蓝色,实际上是使用if else分解光线。
如图所示,我们通过一个条件滤波器实现了信号的三维分离。如果用if else,说明你是在组合图中1/2/3/4的条件,在同一个地方实现条件判断。
要深入了解滤镜的实现细节和细微差别,请参考文章:AOP vs DecoratorOO设计概述。
还有一种伪模式。虽然使用了state等模式,但本质上还是用if else或switch来进行状态切换或者模式内的重要条件判断,这无疑说明还需要进一步的努力。更重要的是,你不能装模作样,出书给人看。
真正掌握这些面向对象的思想是一件困难的事情。目前有各种扯着头发往上拉的解释,都是误导,所以我觉得新手读《Java中的思维》(Java编程思路)没什么用。它试图从语言层面讲OO编程思想,是失败的。可以作为语言参考书,但是作为Java中体现的OO思想的学习资料是错误的。
OO编程思想是一种方法论,没有应用对比,就无法理解这种方法论的特点。禅是一种古老的方法论,悟禅只能通过挑水砍柴来实现。
那么OO思想可以通过什么应用来实现呢?GoF设计模式,等同于软件人员打水、砍柴等基本活动。那么,如果一个程序员连基本的活动都做不到,又怎么能冒充OO程序员呢?从事OO专业的设计和编程,如果不掌握设计模式的基本功,就像是一个不愿意打水漂砍柴的和尚。他为什么要立足于这个行业?我被我的主人赶下山。
最后,在小地方用if else也是可以的,比如简单的数值判断;但是,如果你遵循你的传统思维习惯,在实现业务功能时使用雅思,那就意味着你的思维可能需要重塑。编程经验越丰富,传统的过程思维模式越容易根深蒂固,自己很难改变;建议接受专业的头脑风暴训练。
一句话总结:如果你做了很多系统,很久没用雅思了,说明你可能真的进入OO设计的境地了。(这是我自己实用的衡量和考核标准)。
转自:板桥里http://www.jdon.com人2006年1月11日
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。