理论就不讲了,网上一搜一大把。直接上栗子。
假设我们有个博客系统,有两个简单的业务:新建博文和上传图片集。代码大概是这样的
public static long newBlog(String title, String content, long userId) throws Exception{ User user = User.ME.loadById(userId); if(user==null){ throw new Exception("用户不存在"); } if(User.isFobbiden()){ throw new Exception("用户已被禁止"); } long id = 0; try{ if(StringUtils.isBlank(title)){ throw new Exception("博客标题不能为空"); } if(StringUtils.isBlank(content)){ throw new Exception("博客内容不能为空"); } id = Blog.ME.save(title, content, user.getId()); Listfriends = User.ME.myFriends(user.getId()); UserService.noticeUsers(friends); //通知用户朋友有更新 }catch(Exception e){ throw new Exception(e.getMessage()); } return id; } public static long newPic(String[] picUrls, long userId) throws Exception{ User user = User.ME.loadById(userId); if(user==null){ throw new Exception("用户不存在"); } if(User.isFobbiden()){ throw new Exception("用户已被禁止"); } long id = 0; try{ if(picUrls==null || picUrls.length==0){ throw new Exception("图片地址不能为空"); } id = Pic.ME.save(picUrls, user.getId()); List friends = User.ME.myFriends(user.getId()); UserService.noticeUsers(friends); //通知用户朋友有更新 }catch(Exception e){ throw new Exception(e.getMessage()); } return id; }
可以很容易的看到,这两个业务方法重复代码太多了!怎么优化呢?
讲讲我在菜鸟时期的优化。首先肯定是把重复代码提取出来,写到一个公有的方法。然后其它方法再调用这个公有方法。这里发现头尾都有重复代码,所以会提取出两个公有方法。
优化后的代码如下:
private static User userAuth(long userId) throws Exception{ User user = User.ME.loadById(userId); if(user==null){ throw new Exception("用户不存在"); } if(User.isFobbiden()){ throw new Exception("用户已被禁止"); } return User; } private static void noticeMyFriends(long userId){ Listfriends = User.ME.myFriends(userId); UserService.noticeUser(friends); //通知用户朋友有更新 } public static long newBlog(String title, String content, long userId) throws Exception{ User user = userAuth(userId); long id = 0; try{ if(StringUtils.isBlank(title)){ throw new Exception("博客标题不能为空"); } if(StringUtils.isBlank(content)){ throw new Exception("博客内容不能为空"); } id = Blog.ME.save(title, content, user.getId()); noticeMyFriends(user.getId()); //通知用户朋友有更新 }catch(Exception e){ throw new Exception(e.getMessage()); } return id; } public static long newPic(String[] picUrls, long userId) throws Exception{ User user = userAuth(userId); long id = 0; try{ if(picUrls==null || picUrls.length==0){ throw new Exception("图片地址不能为空"); } id = Pic.ME.save(picUrls, user.getId()); noticeMyFriends(user.getId()); }catch(Exception e){ throw new Exception(e.getMessage()); } return id; }
感觉哪里不太对。
没错,这些都是重复代码!但是怎么优化呢?第一个方法好像在这里没法派上用途。
设计模式是时候登场了!模板模式:减少大量重复代码的必备良药!
首先,我们定义一个接口。
public interface ObjHelper{ public long invoke(User user, Object obj);}然后,定义一个模版方法。基本思路是把差异的代码拿出来,抽象为一个接口,而重复的代码则像是一个模板那样。
private static long newObj(long userId, ObjHelper helper, Object obj){ User user = User.ME.loadById(userId); if(user==null){ throw new Exception("用户不存在"); } if(User.isFobbiden()){ throw new Exception("用户已被禁止"); } long id = 0; try{ //这里是关键的一步 id = helper.invoke(user, obj); Listfriends = User.ME.myFriends(user.getId()); UserService.noticeUsers(friends); //通知用户朋友有更新 }catch(Exception e){ throw new Exception(e.getMessage()); } return id; }
这时候再写新建博文和上传图片集这两个业务方法,就是这么写的了:实现接口,然后调用模板方法。
public static long newBlog(long userId, String title, String content) throws Exception{ ObjHelper helper = new ObjHelper() { @Override public long invoke(User user, Object obj) { long id = 0; if(obj==null){ throw new Exception("博客标题不能为空"); } Blog blog = (Blog)obj; if(StringUtils.isBlank(blog.getTitle())){ throw new Exception("博客标题不能为空"); } if(StringUtils.isBlank(blog.getContent())){ throw new Exception("博客内容不能为空"); } id = Blog.ME.save(blog.getTitle(), blog.getContent(), user.getId()); return id; } }; Blog blog = new Blog(title, content); return newObj(userId, helper, blog); } public static long newPic(long userId, ListpicUrls) throws Exception{ ObjHelper helper = new ObjHelper() { @Override public long invoke(User user, Object obj) { long id = 0; if(obj==null){ throw new Exception("图片地址不能为空"); } List picUrls = (List )obj; if(picUrls.size()==0){ throw new Exception("图片地址不能为空"); } id = Pic.ME.save(picUrls, user.getId()); return id; } }; return newObj(userId, helper, picUrls); }
至此,我们终于消灭重复代码了!
代码大概就是这么写的了,当然最重要的是举一反三,灵活应用。欢迎讨论:-)