避免代码冗余,使用接口和泛型重构Java代码
本文由 ImportNew - ImportNew读者 翻译自 michaelbrameld。如需转载本文,请先参见文章末尾处的转载要求。
【感谢 李云涛(@平等的黑)的热心翻译。如果其他朋友也有不错的原创或译文,可以尝试投递到 ImportNew。】
在使用动态语言和.NET工作了若干年后,我又回到老本行–Java开发。在Ruby中,清除代码冗余是非常方便的,而在Java中则需要结合接口和泛型实现类似的功能。
原始代码
以下是这个类中的一些方法用于后续的阐述。为了使例子更简洁,我移除了些代码。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
publicVfinalK{ Session try{ s ObjectMap return(V) } catch(ObjectGridException { thrownew"Error, } finally { if(snull) s.close(); } returnnull;} publicvoidfinalKfinalV{ Session try{ s ObjectMap map.upsert(key, } catch(ObjectGridException { thrownew"Error, } finally { if(snull) s.close(); } }publicMap<K,extendsK>{ finalList<V>newArrayList<V>(); finalList<K>newArrayList<K>(); keyList.addAll(keys); Session try{ s ObjectMap valueList.addAll(map.getAll(keyList)); } catch(ObjectGridException { thrownew"Error, } finally { if(snull) s.close(); } Map<K,newHashMap<K, for(inti0; map.put(keyList.get(i), } returnmap;} |
遇到的问题
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
Sessiontry{ s ObjectMap //}catch(ObjectGridException{ thrownew"Error,}finally{ if(snull) s.close(); } |
上面的代码段几乎存在于类的每个方法中,这违反了DRY原则 。将来如果需要改变检索Session 和 ObjectMap实例的方式,或着某天这段代码被发现有缺陷,我们就不得不修改每个(包含这段代码的)方法,因此需要找到一种方式来复用这些执行代码。
重构后的代码
为了传递包含了原方法中业务逻辑的实例,我们创建一个带有抽象方法的 Executable 接口 。execute()方法参数为我们欲操作的ObjectMap实例。
|
1
2
3
|
interfaceExecutable<T> publicTthrowsObjectGridException;} |
由于我们的目的仅仅是在每个方法中操作ObjectMap实例,可以创建executeWithMap()方法封装前述的那一大段重复代码。这个方法的参数是Executable接口的实例,实例包含着操作map的必要逻辑(译者注:这样Executable接口的实例中就是纯粹的业务逻辑,实现了解耦合)。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private<T>{ Session try{ s ObjectMap // returnex.execute(map); } catch(ObjectGridException { thrownew"Error, } finally { if(snull) s.close(); }} |
现在,可以用如下形式的模板代码替换掉第一个例子中的代码:这个模板创建了一个匿名内部类,实现了Executable接口和execute()方法。其中execute()方法执行业务逻辑,并以getXXX()的方式返回结果(若为Void方法,返回null)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
publicVfinalK{ returnexecuteWithMap(newExecutable<V>() publicVthrowsObjectGridException { return(V) } }); } publicvoidfinalKfinalV{ executeWithMap(newExecutable<Void>() publicVoidthrowsObjectGridException { map.upsert(key, returnnull; } }); }publicMap<K,extendsK>{ finalList<K>newArrayList<K>(); keyList.addAll(keys); List<V>newExecutable<List<V>>() publicList<V>throwsObjectGridException { returnmap.getAll(keyList); } }); Map<K,newHashMap<K, for(inti0; map.put(keyList.get(i), } returnmap;} |
FunctionalInterface Annotation (功能接口注释)
Java 8 的 @FunctionalInterface annotation 使这一切变的简单。若某接口带有一个抽象方法,这个接口便可以被用作为lambda表达式的参数,称为功能接口。
|
1
2
3
4
|
@FunctionalInterfaceinterfaceExecutable<T> publicTthrowsObjectGridException;} |
只要接口仅仅包含一个抽象方法,便可以使用这个annotation。这样就能减少相当数量的模板代码。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
publicVfinalK{ returnexecuteWithMap((ObjectMap} publicvoidfinalKfinalV{ executeWithMap((ObjectMapreturnnull;}publicMap<K,extendsK>{ finalList<K>newArrayList<K>(); keyList.addAll(keys); List<V> Map<K,newHashMap<K, for(inti0; map.put(keyList.get(i), } returnmap;} |
结论
实现这些重构我很开心。它比原始的代码略复杂一点,但是更简明,更DRY,所以一切都是值得的。 尽管还有提升的空间,但这是一个良好的开始。
原文链接: michaelbrameld 翻译: ImportNew.com- ImportNew读者
译文链接: http://www.importnew.com/6761.html
避免代码冗余,使用接口和泛型重构Java代码的更多相关文章
- 重构Java代码的既有设计-影片出租店
案例:计算每位顾客的消费金额并打印详细信息.顾客租赁了哪些影片,租期多长,根据租赁时间和影片类型计算出费用.影片分为3类:儿童片,新片,普通片.此外需计算该顾客的积分. Movie: public c ...
- 让JAVA代码跑得更快
本文简单介绍一下在写代码过程中用到的一些让JAVA代码更高效的技巧. 1. 将一些系统资源放在池中(如数据库连接, 线程等) 在standalone的应用中, 数据库连接池可以使用一些开源的连接池 ...
- 使用非java代码编程
使用非JAVA代码 JAVA语言及其标准API(应用程序编程接口)应付应用程序的编写已绰绰有余.但在某些情况下,还是必须使用非JAVA编码.例如,我们有时要访问操作系统的专用特性,与特殊的硬件 ...
- Android逆向-java代码基础
作者:I春秋作家——HAI_ 0×00 前言 看这篇可以先看看之前的文章,进行一个了解.Android逆向-java代码基础(1)Android逆向-java代码基础(2) 之前看到有大佬用smali ...
- 【Android】通过Java代码替换TabHost中的drawableTop资源
在博客 http://blog.csdn.net/jueblog/article/details/11837445 中的Tab选项卡中, 点击相应的Tab选项,图标没有发生改变. 这些资源图片也没有尽 ...
- Java代码块详解
Java中代码块指的是用 {} 包围的代码集合,分为4种:普通代码块,静态代码块,同步代码块,构造代码块 普通代码块: 定义:在方法.循环.判断等语句中出现的代码块 修饰:只能用标签修饰 位置:普通代 ...
- java代码块的理解
最近在复习java基础,在看到java代码块的时候,忽然发现自己貌似对于java代码块一无所知,于是赶紧对着一些资料实战演练了一把. 对于java代码块,不难根据名称看出其实就是一些java语句的集合 ...
- 阿里官方Java代码规范标准《阿里巴巴Java开发手册 终极版 v1.3.0》
终极版 v1.3.0 2017年开春之际,阿里诚意献上重磅大礼:<阿里巴巴Java开发手册>,首次公开阿里官方Java代码规范标准.这套Java统一规范标准将有助于提高行业编码规范化水平, ...
- 在js中嵌套java代码
jsp中有时候在js中操作某些java后台传递过来的数据逻辑比较复杂,比如list内容的遍历,可以直接在页面上添加java脚本来执行内容,代码如下: //在js中插入java代码操作 <% // ...
- 阿里官方Java代码规范标准《阿里巴巴Java开发手册》下载
https://bbs.aliyun.com/read/306592.html?page=e 2017年开春之际,诚意献上重磅大礼:阿里巴巴Java开发手册,首次公开阿里官方Java代码规范标准. 这 ...
随机推荐
- (Ljava/lang/String;)Ljava/util/List;
背景:原正常代码,更改类名后,重新运行 报错:(Ljava/lang/String;)Ljava/util/List; 解决:mvn clean 后 compile,再运行,正常
- JS处理html的编码(encode)与解码(decode)
一.用浏览器内部转换器实现转换 代码: var HtmlUtil = { // 1.用浏览器内部转换器实现html编码 htmlEncode: function(html) { // 创建一个元素容器 ...
- HTML – HTML Tags & Semantic HTML 语义化 HTML
前言 HTML tag 有 100 多个, 有些是功能形的, 非用不可, 有些是为了语义化对 screen reader 友好 (给眼睛有残缺的人也可以获取清晰的网站信息). 语义化是很重要的, 有些 ...
- SpringMVC —— RESTful入门
RESTful入门案例 1.设定http请求动作(动词) @RequestMapping(value = "/users",method = RequestMethod.POS ...
- Java远程连接服务器实现文件上传下载及目录操作
详情请阅读原文 在其基础之上做了进一步的封装 <!-- https://mvnrepository.com/artifact/com.jcraft/jsch --> <depende ...
- 北京智和信通亮相2023IT运维大会,共话数智浪潮下自动化运维新生态
2023年9月21日,由IT运维网.<网络安全和信息化>杂志社联合主办的"2023(第十四届)IT运维大会"在北京成功举办.大会以"以数为基 智引未来&quo ...
- 41.key发生变化,dom还会复用吗
会复用但是可能会产生没有必要的真实DOM更新 ,会降低渲染效率 :比如使用 index 作为 key 值 :
- 使用 GitLab 账号登陆 KubeSphere
作者:李帅 介绍 KubeSphere 多租户是实际生产使用中非常需要的一个功能,该功能满足不同用户登陆 KubeSphere 平台的需求.比如开发,运维,测试都需要登陆 KubeSphere 平台, ...
- 用easyVget下载B站油管视频
B站油管等视频平台简直就是无所不有的宝库,动漫.番剧.纪录片.科普,更有海量的学习资源,可以极大地满足你的视觉欲和求知欲. 作为一只视频仓鼠,我热衷于下载自己感兴趣的视频到本地,不用担心视频被和谐.不 ...
- 网络应用模型的经典分类:C/S 与 P2P
网络应用无处不在,从我们日常使用的社交媒体到远程文件传输,网络应用模型是支撑这些通信和服务的基础架构.通常,这些网络应用根据其结构原理可以被大致划分为两大类:C/S(Client/Server)模型和 ...