`
ajoo
  • 浏览: 452717 次
社区版块
存档分类
最新评论
阅读更多
这里讲述的是一个非常让人尴尬的故事

我们有一个简单的java类:
class Details {
  double getBalance();
  double getFixed();
  double getVariable();
  double getSpendDown();
  ...
  //各种getter以及其他相关的逻辑
}


现在业务逻辑需要对一些property做求和操作,求overallBalance, overallFixed之类的。
没什么了不起的,一个for循环分分钟搞定:
static double getOverallBalance(Details[] arr){
  double sum = 0;
  for(int i=0; i<arr.length; i++) {
    sum += arr[i].getBalance();
  }
}


同理,对overallFixed,代码大同小异,copy-paste先。
static double getOverallFixed(Details[] arr){
  double sum = 0;
  for(int i=0; i<arr.length; i++) {
    sum += arr[i].getFixed();
  }
}


这都没什么。可是当我写到第七个getOverallBlahBlah(arr)函数的时候,终于有点受不了了。这代码重复的虽然不多,但是架不住这么没完没了阿。

作为code-against-interface的推崇者,作为一个函数式编程的扇子,最自然的想法就是把不同的getter逻辑抽象成一个Getter接口,如下:
interface Getter {
  double get(Details details);
}
static double sum(Details[] arr, Getter getter){
  double sum = 0;
  for(int i=0; i<arr.length; i++) {
    sum += getter.get(arr[i]);
  }
}

娜爱思啊。有比这代码更优雅的么?

然后各个求和的代码变成:
double overallBalance = sum(details, new Getter(){
  public double get(Details details){
    return details.getBalance();
  }
});
double overallFixed = sum(details, new Getter(){
  public double get(Details details){
    return details.getFixed();
  }
});
....

嗯。几乎没有什么重复的逻辑了。

不过......
数数代码行数,怎么没有减少,反而略有盈余?仔细找找。发现原来的for loop是四行,现在的new Getter(){...}居然也是四行!!!
再加上一个sum()函数,我辛苦了半天的重构,居然代码行数增加了!

如果世界上有比一个java的匿名类的语法更臭的,那大概就是两个匿名类语法了。据说居然还有人质疑java 7引入closure语法的意义?

另一个方法是用apache commons beanutils的getProperty(),最终的语法会是:
double overallBalance = sum(details, "balance");

语法足够简单了,但是重构的时候就麻烦了,也没有code-completion可用。

尴尬阿。这么一个简单的for loop,用匿名类重构似乎不值得。但是就任由这七个(也许回头还会更多)长得一模一样的for loop这么站在这气我?

走投无路,开始琢磨奇技淫巧了。

先声明一个接口,来包含所有需要sum的property getter。
private interface IDetails {
  double getBalance();
  double getFixed();
  double getVariable();
  double getSpendDown();
  ...
  //所有其它需要做sum的getter
}


然后让Details实现IDetails。Details的代码不用变。
class Details implements IDetails {
  ...
  //代码不变
}


戏肉来了。写一个dynamic proxy,来封装sum逻辑。
static IDetails sumOf(final IDetails[] arr){
  return (IDetails)Proxy.newProxyInstance(
    getClass().getClassLoader(), new Class[]{IDetails.class}, new InvocationHandler(){
    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
      double sum = 0;
      for(int i=0; i<arr.length; i++) {
        sum += ((Double)method.invoke(arr[i], args)).doubleValue();
      }
      return new Double(sum);
    }
  });
}



好了,接下来求sum的语法可以被简化为如下:
double overallBalance = sumOf(arr).getBalance();
double overallFixed = sumOf(arr).getFixed();
...


而且,再需要sum新的property,只需要把这个getter放进IDetails接口,就大功告成了。


很有趣的dynamic proxy应用。不过,一个求和这么简单的事情居然要动用这种奇技淫巧,很值得自豪么?

要是在ruby里,我就直接:
sum(arr){balance}


该死的java啊!
分享到:
评论
4 楼 losing_fox 2006-12-20  
昨天看了一个smalltalk的简单介绍,的确很为这种语言的灵活性所震惊

像楼主所描述的技巧,在很多脚本语言里都很常见

我的疑惑就是这些技巧所带来的好处和这些技巧对于入门难度的影响

哪个更大一些

3 楼 byk 2006-12-20  
发错,,,不好意思
2 楼 byk 2006-12-20  
能用,,,具体用来干什么,需要自己写代码实现..



在你自己的 servlet ,覆写javax.servlet.http.HttpServlet 里的方法实现自己需要的功能

public doPut(request,response){
///do something

}

public doDelete(request,response){
///do something

}
1 楼 Eastsun 2006-12-20  
长见识了.

相关推荐

    Python 语言有什么奇技淫巧吗?.docx

    Python 语言奇技淫巧总结 Python 语言作为一种高效、灵活的编程语言,具有许多奇技淫巧,可以帮助开发者提高编程效率和代码质量。在本文中,我们将探讨 Python 语言中的四大奇技淫巧:循环代码优化、异常处理,以及...

    来自小密圈里的那些奇技淫巧.pdf

    标题中提到的“来自小密圈里的那些奇技淫巧”可能是指在特定的技术圈子中分享的一些特殊技巧,用于突破安全限制和进行有效的攻击测试。以下将详细解释文档中提及的各个技巧: 1. EVAL长度限制突破技巧: 在PHP中,`...

    Python那些事——python的奇技淫巧

    Python,作为一门广受欢迎的编程语言,在...总之,Python的这些“奇技淫巧”展示了这门语言在实际编程中灵活多变的应用能力,对于学习和使用Python的开发者而言,了解这些技巧能够极大地提高开发效率和程序的用户体验。

    算法心得-高效算法的奥秘(原书第2版)_带书签_高清_[位运算的奇技淫巧].pdf

    《算法心得-高效算法的奥秘(原书第2版)》是一本深入探讨算法精髓的书籍,...书中的"位运算的奇技淫巧"部分,无疑是将这种技术运用到极致的探索,对于有志于提升算法水平的开发者来说,是一份不可多得的参考资料。

    vue有哪些奇技淫巧.md

    vue有哪些奇技淫巧

    JavaScript奇技淫巧45招 _ 不可能不确定1

    JavaScript是世界上最流行的编程语言之一,尤其在Web开发领域中占据着核心地位。它不仅可以用于创建交互式的网页,还可以用于移动应用开发、服务器端编程...在JavaScript的世界里,还有很多其他的奇技淫巧等待探索。

    渗透中关于dns的奇技淫巧.pdf

    【DNS基础及安全应用】 DNS(Domain Name System)是互联网中的关键组件,负责将人类可读的域名转换为网络可以理解的IP地址。其工作原理是通过查询和响应机制,确保用户能正确访问网络资源。当用户输入一个域名时,...

    RocketMQ 奇技淫巧之 ServiceLoader 源码解读 - GitChat

    RocketMQ 奇技淫巧之 ServiceLoader 源码解读 抓下来打包成了HTML文件, 方便离线观看

    开源电子书《JavaScript奇技淫巧》,本书向您分享一系列新奇、有趣、有技术含量的 JavaScript 编程技术

    开源电子书《JavaScript奇技淫巧》,『奇技淫巧』一词出自古籍《书·泰誓下》,指新奇的技艺和作品。此词意与本书内容十分契合,因此书名借用该词。

    Go-Git的奇技淫巧

    在这个“Go-Git的奇技淫巧”中,我们将探讨一些高级和实用的Git技巧,以及如何使用Go来进一步操作Git。 1. **分支管理**:Git的分支机制允许开发者在同一项目上并行工作。`git branch`命令用于创建、查看和切换分支...

    Java 8中Stream API的这些奇技淫巧!你Get了吗?

    Java 8 中 Stream API 的奇技淫巧 Java 8 中的 Stream API 是一种功能强大且实用的数据处理工具,能够帮助开发者更高效地处理数据。Stream API 的出现是为了解决 Java 中处理数据的痛点,提供了一种简洁、灵活、...

    Git的奇技淫巧

    Git的奇技淫巧在软件开发领域中是一个广泛讨论的话题,因为它的功能强大且灵活性极高。Git不仅仅是一个“分布式版本管理工具”,它还是一个能够帮助开发者跟踪代码变化、协同工作和回溯错误的强大系统。在JavaScript...

    C语言中的奇技淫巧

    C语言中的奇技淫巧 C语言是一门功能强大且灵活的编程语言,学习C语言的过程中,总会遇到很多令人眼前一亮的代码,尤其是你写了几十行的代码,别人只用了简单几行的递归就实现的功能。下面我们就总结几个C语言中比较...

    CSS中边框使用负边距值的奇技淫巧

    标题“CSS中边框使用负边距值的奇技淫巧”暗示了负边距在CSS中的独特应用,这些应用可能并不常见,但能够解决特定的布局挑战。描述提到,通过负边距可以进行布局调整和实现元素重叠,这些都是设计师和开发者可以利用...

    移动端Ui自动化上的正经奇技淫巧Havefun

    在移动端UI自动化测试中,"正经奇技淫巧Havefun"这个标题暗示了我们将探讨一些巧妙而实用的技术,这些技术可能不广为人知,但能显著提高我们的工作效率。混合移动开发,特别是JavaScript开发,是现代移动应用开发的...

    Git的奇技淫巧.zip

    Git是一个 “分布式版本管理工具”,简单的理解版本管理工具:大家在写东西的时候都用过 “回撤” 这个 功能,但是回撤只能回撤几步,假如想要找回我三天之前的修改,光用 “回撤” 是找不回来的。...

    bash奇技淫巧

    ### bash奇技淫巧 #### 简介 在日常的Linux使用过程中,熟练掌握Bash的一些技巧可以极大地提升工作效率。本文将分享一系列实用的Bash小贴士,旨在帮助那些经常与Linux命令行打交道的人们更好地利用Bash的强大功能...

    Python-收集到的一些src挖掘奇技淫巧

    这个压缩包文件"Python-收集到的一些src挖掘奇技淫巧"可能是包含了一系列用于Python源代码安全检查和分析的技巧和工具。下面我们将深入探讨一些相关的知识点。 1. **源代码分析**:这是对软件项目源代码进行的详细...

Global site tag (gtag.js) - Google Analytics