锁定老帖子 主题:用enum代替if.这个设计大家怎么看
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-10-08
抛出异常的爱 写道 albeter 写道 十一闲来无事到公司改了段代码,大家看看这个修改适合不。首先放出修改前的原始的代码(经过简化,改了名字,名字随便改的),逻辑很简单,就是前端传一个参数进来,后台根据参数的不同进行不同的逻辑处理。
public class HandleSomething { private Manager manager; private Logger subLogger = LoggerFactory.getLogger(this.getClass()); /** * entryType ,进入的参数,根据该参数来判断逻辑。 * */ public static final int VIP_ENTRY_FLOW = 1; // 特殊页面进入 public static final int INDEX_ENTRY_FLOW = 2; // 首页进入 public static final int OTHERS_ENTRY_FLOW = 3; // 其他页面进来 protected void work( int entryType, long userId,Context context) { if (entryType == VIP_ENTRY_FLOW) { context.put("type", vipFlow(userId,context)); return; } if (entryType == INDEX_ENTRY_FLOW) { context.put("type", indexFlow(userId, context)); return; } if (entryType == OTHERS_ENTRY_FLOW) { context.put("type", othersFlow(userId,context)); } } private int vipFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/} private int indexFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/} private int othersFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/} } 修改后: public class HandleSomething { private static Manager manager; private static Logger subLogger = LoggerFactory.getLogger(HandleSomething.class); protected void work( int entryType, long userId,Context context) { for (Flow flow : Flow.values()) { if (flow.getTag() == entryType) { context.put("type", flow.handle(userId, context)); break; } } } enum Flow{ VIP_ENTRY_FLOW (1) {// 特殊页面进入 @Override int handle(long userId, Context context) { /*这里的逻辑用到manager和subLogger*/ }, INDEX_ENTRY_FLOW (2) {// 首页进入 @Override int handle(long userId, Context context) { /*这里的逻辑用到manager和subLogger*/ }, OTHERS_ENTRY_FLOW (3){ // 其他页面进来 @Override int handle(long userId, Context context) { /*这里的逻辑用到manager和subLogger*/ } }; private final int tag; Flow(Integer tag){ this.tag=tag; } public int getTag() { return tag; } public abstract int handle(long userId, Context context); } } 修改后通过使用枚举类型间接地去掉了if. 我觉得修改之后有以下特点: 优点:1.execute方法的代码更简洁并且减少重复代码 2.如果要增加新的处理流程只需要在枚举类中增加一个参数类型即可,不用修改execute方法 但是我有个问题:不清楚这样写是否会带来其他问题。例如性能问题和内存问题。 大十一的写代码?想过劳死么? 1.这代码最大的问题在于contex的管理。。。。 太分散了。 但你引入的东西没有解决这个问题 2.Enum 的生成方式有无数种 if (flow.getTag() == entryType) { 这是最差的一种 create可以写在FLOW中 返回一个 public staitc flow getInstents(int type) 自己实现一下吧 3.操作区分应该放到enum中而不是把不同处抽象后让其它人来实现 把逻辑放到enum里面?java的enum能干的事儿太多了,缺乏简单性。不过套路也不见得错,代码把==改为valueOf立马就解决了。 |
|
返回顶楼 | |
发表时间:2012-10-08
1、我还是停留在java 1.4版本,enum 这个关键字还不知道干嘛的呢。
2、楼主,学习重构是不断实践的,虽然你现在做的不好,也许这是你实践的必经过程,即使你是生搬硬套设计模式也要去试试; 3、你重构的目的是什么?让代码好看?为了方面维护? 4、从你代码来看,这个重构是必要的,也许说不定那天要从某个指定的页面进入呢? 5、你的代码,多了个for循环、还有if语句,这两个都可以省的,上面有人提示,你试试看。 5、关于并发的问题,要看看你的内存(java中的对象)是否同时被多个线程修改!在spring中bean默认是单例的,所以bean的属性不能被多个线程修改,否则就有并发问题。也就是对象的有状态无状态问题了。 |
|
返回顶楼 | |
发表时间:2012-10-08
我觉得这个重构并不是很好,其实只是if的另一种写法而已(哪种更好暂且不论)。如果第一个参数增加了一个值呢?重构后的代码依然要修改,原本if的写法也一样
如果用多态来重构它会更好 |
|
返回顶楼 | |
发表时间:2012-10-08
嗯,这个是不怎么好。一般用多态来代替if。
好坏得先有个标准来判断,你先给个判断标准。 |
|
返回顶楼 | |
发表时间:2012-10-08
devroller2 写道 嗯,这个是不怎么好。一般用多态来代替if。
好坏得先有个标准来判断,你先给个判断标准。 好的标准我认为是以下几点: 1.逻辑上使用较少的if,3个以下; 2.在新增type时,不影响(修改)原有代码; 3.程序可读性强; |
|
返回顶楼 | |
发表时间:2012-10-08
albeter 写道 十一闲来无事到公司改了段代码,大家看看这个修改适合不。首先放出修改前的原始的代码(经过简化,改了名字,名字随便改的),逻辑很简单,就是前端传一个参数进来,后台根据参数的不同进行不同的逻辑处理。
public class HandleSomething { private Manager manager; private Logger subLogger = LoggerFactory.getLogger(this.getClass()); /** * entryType ,进入的参数,根据该参数来判断逻辑。 * */ public static final int VIP_ENTRY_FLOW = 1; // 特殊页面进入 public static final int INDEX_ENTRY_FLOW = 2; // 首页进入 public static final int OTHERS_ENTRY_FLOW = 3; // 其他页面进来 protected void work( int entryType, long userId,Context context) { if (entryType == VIP_ENTRY_FLOW) { context.put("type", vipFlow(userId,context)); return; } if (entryType == INDEX_ENTRY_FLOW) { context.put("type", indexFlow(userId, context)); return; } if (entryType == OTHERS_ENTRY_FLOW) { context.put("type", othersFlow(userId,context)); } } private int vipFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/} private int indexFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/} private int othersFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/} } 修改后: public class HandleSomething { private static Manager manager; private static Logger subLogger = LoggerFactory.getLogger(HandleSomething.class); protected void work( int entryType, long userId,Context context) { for (Flow flow : Flow.values()) { if (flow.getTag() == entryType) { context.put("type", flow.handle(userId, context)); break; } } } enum Flow{ VIP_ENTRY_FLOW (1) {// 特殊页面进入 @Override int handle(long userId, Context context) { /*这里的逻辑用到manager和subLogger*/ }, INDEX_ENTRY_FLOW (2) {// 首页进入 @Override int handle(long userId, Context context) { /*这里的逻辑用到manager和subLogger*/ }, OTHERS_ENTRY_FLOW (3){ // 其他页面进来 @Override int handle(long userId, Context context) { /*这里的逻辑用到manager和subLogger*/ } }; private final int tag; Flow(Integer tag){ this.tag=tag; } public int getTag() { return tag; } public abstract int handle(long userId, Context context); } } 修改后通过使用枚举类型间接地去掉了if. 我觉得修改之后有以下特点: 优点:1.execute方法的代码更简洁并且减少重复代码 2.如果要增加新的处理流程只需要在枚举类中增加一个参数类型即可,不用修改execute方法 但是我有个问题:不清楚这样写是否会带来其他问题。例如性能问题和内存问题。 用swtich就能解决的问题,为什么非得弄得那么复杂呢?性能比你们这两个都要快啊 |
|
返回顶楼 | |
发表时间:2012-10-09
最后修改:2012-10-09
看了大家的回复收获蛮多的。
1.首先在work中的for循环的确是需要抽取到Flow类内部,修改完的方法如下: public static Flow getInstance(Integer entryType){ for (Flow flow : Flow.values()) { if (flow .getTag()==entryType) { return flow ; } } } 然后是说到的是怎么获取枚举实例的问题,我这里用的是判断枚举对象中tag的值是否与参数entryType的值相同,相同的话就返回该对象。如果设定的参数是Integer类型的话,我能想到的获取枚举对象的方法最好也就是以上的写法了。(当然你想把==改成equals()也是问题的)thinking in java 中枚举一章有那么一句话"我们只能在enum定义的内部使用其构造器创建enum实例,一旦enum的定义结束,编译器就不允许我们再使用其构造器来创建任何实例了"。倒是如果把entryType改为传入String类型的话,可以使用 Flow.valueOf(entryType);来获取实例,这样更简洁。 2.还有位朋友说到表驱动,其实策略枚举就是一种表驱动的表现。 3.另外就是Context的管理过于分散的问题,我的想法是可以先把Flow中的handle()方法设计为Result handle()把需要的数据用一个封装的类Result来返回。然后在外层的work方法中再统一用Context的处理。不过这样做的话,会显得更复杂,需要权衡。 4.有些朋友说到该不该重构这个类的问题,我谈谈我自己看法,重构,目的是让程序的层次更加的清晰,让别人或者自己看着更舒服,如果该程序的代码要被复用或者增加修改的概率比较大,那么需要更多的去考虑可扩展性问题。但是有时候凭空想象的话,很难判断重构完之后的代码是否能达到以上的标准。所以不妨先把代码按自己的想法重构了,再和原来的代码对比。即使最后不采用,中间的过程也能促进自己的思考。:) |
|
返回顶楼 | |
发表时间:2012-10-09
公司给你放假,还不出去玩,闲来无事你咋不去把妹子去呢,活脱一个屌丝
|
|
返回顶楼 | |
发表时间:2012-10-09
夜神月 写道 公司给你放假,还不出去玩,闲来无事你咋不去把妹子去呢,活脱一个屌丝
屌丝的命,没办法。 |
|
返回顶楼 | |
发表时间:2012-10-09
还不如扔个MAP里呢,通过传入不同的KEY,取出不同的处理策略。
|
|
返回顶楼 | |