论坛首页 Java企业应用论坛

用enum代替if.这个设计大家怎么看

浏览 29661 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-10-04   最后修改:2012-10-04
十一闲来无事到公司改了段代码,大家看看这个修改适合不。首先放出修改前的原始的代码(经过简化,改了名字,名字随便改的),逻辑很简单,就是前端传一个参数进来,后台根据参数的不同进行不同的逻辑处理。
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方法

但是我有个问题:不清楚这样写是否会带来其他问题。例如性能问题和内存问题。

   发表时间:2012-10-04  
没人想吐槽下?
0 请登录后投票
   发表时间:2012-10-04  
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中而不是把不同处抽象后让其它人来实现
0 请登录后投票
   发表时间:2012-10-04  
受教了。第三点不是很明白,你的意思是不要把具体的方法实现写到enum中?
0 请登录后投票
   发表时间:2012-10-05  
albeter 写道
受教了。第三点不是很明白,你的意思是不要把具体的方法实现写到enum中?

把变化的部分放在enum中可以让主体代码更简单清楚。
0 请登录后投票
   发表时间:2012-10-05  
抛出异常的爱 写道
albeter 写道
受教了。第三点不是很明白,你的意思是不要把具体的方法实现写到enum中?

把变化的部分放在enum中可以让主体代码更简单清楚。

明白了,还有一个问题是,用static 修饰了Manager是否会造成并发问题?因为如果没用static修饰的话每个HandleSomething实例spring都会创建一个新的Mannger实例,而用了static之后就是每个实例都共享Manager,请问并发量高的时候是否会造成并发问题?
0 请登录后投票
   发表时间:2012-10-05  
策略枚举啊
0 请登录后投票
   发表时间:2012-10-07  
楼主的重构挺巧妙的,很适宜长远的扩展。至于性能啥的,只要你这个不是每秒跑成本上千次的,都不用考虑的
0 请登录后投票
   发表时间:2012-10-08  
纯粹就是没事找事,看到大家说if不好,就想着方地把if去掉,有这必要吗?有这个必要吗?
1 请登录后投票
   发表时间:2012-10-08   最后修改:2012-10-08
第3点的意思是说,应该这样
protected void work( int entryType, long userId,Context context)  { 
       Flow.getInstance(entryType).handle(userId,context);
}

自己可以网上看看“策略枚举”或“策略模式”
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics