论坛首页 Java企业应用论坛

Spring Method Replacement

浏览 4879 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-10-19  
http://jroller.com/comments/habuma/Weblog/spring_method_replacement

引用

public abstract class AbstractRecorder implements Recorder {
  public abstract void record();;
  public abstract void playback();;
}


The actual implementations of record() and playback() are left abstract (<replaced-method> works just fine with abstract methods). This leaves it up to me to create implementations of these methods to define the mechanisms by which recording and playback are performed.

For example, I could implement record() as recording to tape, CD, or MP3. At the same time, I could implement playback() to play to a speaker, over the radio airwaves, or maybe across a phone line.

If I were to create subclasses to cover all of the possible combinations of record() and playback() implementations mentioned above, I'd end up with at least 9 subclasses of AbstractRecorder (3 recording implementations times 3 playback implementations). If I were to add another recording implementation I'd end up creating 3 more subclasses; one for each of the playback implementations.

But if I were to use Spring's <replaced-method> I'd only need to create one replacer class for each recording implementation and one replacer class for each playback implementation. Then I'd piece together the chosen record-playback combination in Spring's configuration file when I declare the "recorder" bean:
<beans>  
  <bean id="recorder" class="com.habuma.wiring.AbstractRecorder">
    <replaced-method name="record" replacer="recordDevice"/>
    <replaced-method name="playback" replacer="playbackDevice"/>
  </bean>
      
  <bean id="recordDevice"
      class="com.habuma.wiring.TapeRecorder"/>
  <bean id="playbackDevice"
      class="com.habuma.wiring.SpeakerPlayback"/>
</beans>


As wired here, I've declared the "recorder" bean to be a simple tape recorder. It records to tape and plays back to a speaker. If I decide later that I need the playback to be over the radio instead a speaker, I just switch the "playbackDevice" bean's class to be "com.habuma.wiring.RadioPlayback". Likewise, I can swap out the "recordDevice" bean's class with "com.habuma.wiring.Mp3Recorder" to record to MP3.


这个东西看起来很好玩,但是我一时还没想到有什么用。大家来探讨一下吧。
   发表时间:2004-10-19  
是挺好玩的,不过我也看不出什么用来,好像还鼓励乱写代码了
0 请登录后投票
   发表时间:2004-10-19  
第一个例子看不出什么作用,第二个却是很有趣。
这篇blog让我想起了荣耀先生网站上的一篇文章《委托和事件》

通过这种方法,我可以只实现我关心的接口,比如例子中record,而不必理会playback的存在。
实际的测试证明,如果我只用一个Replacer实现了record,只要我不去调用playback,万事OK。

例子完全可以再改进一下,用接口,连抽象类都省略,这样看得更清楚。

这是又是一种利用Cglib动态生成类的做法,对于动态生成技术的运用倒是一天天多了起来。

不过,正如femto所说,这种东西不太容易理解,很容易造成误用。
还有,使用这种方法,就会将代码绑定在Spring上,看看Replacer实现的接口就知道了。而且从代码上很难看出这个Replacer同Recorder的关联,这样也会增加理解的复杂程度。
看来随着Spring运用的日益广泛,使用得越是高级,被绑定的可能性越大,那样的话,Spring宣扬的不依赖API就成了鬼话。
0 请登录后投票
   发表时间:2004-10-19  
dreamhead 写道
第一个例子看不出什么作用,第二个却是很有趣。
这篇blog让我想起了荣耀先生网站上的一篇文章《委托和事件》

通过这种方法,我可以只实现我关心的接口,比如例子中record,而不必理会playback的存在。
实际的测试证明,如果我只用一个Replacer实现了record,只要我不去调用playback,万事OK。

例子完全可以再改进一下,用接口,连抽象类都省略,这样看得更清楚。

这是又是一种利用Cglib动态生成类的做法,对于动态生成技术的运用倒是一天天多了起来。

不过,正如femto所说,这种东西不太容易理解,很容易造成误用。
还有,使用这种方法,就会将代码绑定在Spring上,看看Replacer实现的接口就知道了。而且从代码上很难看出这个Replacer同Recorder的关联,这样也会增加理解的复杂程度。
看来随着Spring运用的日益广泛,使用得越是高级,被绑定的可能性越大,那样的话,Spring宣扬的不依赖API就成了鬼话。


中午跟TrustNo1聊了一下,觉得现在玩Java也有点像头两年玩C++,有点挑战极限的味道了——C++玩的是template,Java玩的是动态代理。不过,你担心的API绑定我倒不觉得有什么问题。比如说TapeRecorder的实现,你可以把它做成一个functor:

public class RecordOnTape implements UnaryFunction {
  public Object evaluate(Object arg0); {
    String content = (String); arg0;
    return new Tape(content);;
  }
}


实现Replacer的时候就直接委派给这个functor:

public Object reimplement(Object target, Method method, Object[] args); {
  return new RecordOnTape();.evaluate(args[0]);;
}


我现在写程序喜欢把所有重要操作都变成一个functor,以后不管是循环list还是遍历树,只要遇到同样的操作都可以复用functor。
0 请登录后投票
   发表时间:2004-10-19  
正如C++之父前几年所说,Java之所以简单是因为它还在发展之中。从Tiger出笼开始,Java发生了巨大的变化。前不久看了篇讨论Java 7.0的文章《Evolving the Java Language》,如果真要以此演化下去,Java便再也无法称自己为简单了。

有一种程序设计语言叫D,看了它的语法给我的感觉是,要什么有什么。我一直认为C++的语法就够复杂了,它居然比C++的东西还多。这种语言对于高手来说,具备几乎一切的便利,对于新手来说,可能学了半天都不知道北在哪里。

在语言进化之前,现在Java的动态代码生成技术已经有些让人眼花缭乱了。尤其在用了各种框架之后,给人的感觉是,程序是我写的,我却搞不清楚它是怎么运行的。这应该算把Java程序员的门槛又提高了吧!用这种办法来保证自己不会轻易贬值,也是一种不错的主意。^_^

functional programming让人感觉很新鲜,但在实际的代码中运用,我一直没有很好的理解。
gigix,给出一些你的感受如何?
0 请登录后投票
   发表时间:2004-10-19  
我觉得很多东西都是语法糖衣。看看scheme,什么都没有,就是define、lambda、函数调用,够用了。你可能说,语法简单就意味着编译器检查少,程序规模大了就容易出错。但是我现在用一种类似于FP的方式写了些Java代码,也不觉得特别容易出错,因为每个小功能——小到什么程度?譬如一次循环中的那个操作——都是一个functor,都可以独立测试,而整个程序是在这些可以独立测试的functor之上组装起来的。

我在站内短信给你留了东西,你先看看吧。
0 请登录后投票
   发表时间:2004-11-20  
gigix 写道
http://jroller.com/comments/habuma/Weblog/spring_method_replacement

引用

public abstract class AbstractRecorder implements Recorder {
  public abstract void record();;
  public abstract void playback();;
}


The actual implementations of record() and playback() are left abstract (<replaced-method> works just fine with abstract methods). This leaves it up to me to create implementations of these methods to define the mechanisms by which recording and playback are performed.

For example, I could implement record() as recording to tape, CD, or MP3. At the same time, I could implement playback() to play to a speaker, over the radio airwaves, or maybe across a phone line.

If I were to create subclasses to cover all of the possible combinations of record() and playback() implementations mentioned above, I'd end up with at least 9 subclasses of AbstractRecorder (3 recording implementations times 3 playback implementations). If I were to add another recording implementation I'd end up creating 3 more subclasses; one for each of the playback implementations.

But if I were to use Spring's <replaced-method> I'd only need to create one replacer class for each recording implementation and one replacer class for each playback implementation. Then I'd piece together the chosen record-playback combination in Spring's configuration file when I declare the "recorder" bean:
<beans>  
  <bean id="recorder" class="com.habuma.wiring.AbstractRecorder">
    <replaced-method name="record" replacer="recordDevice"/>
    <replaced-method name="playback" replacer="playbackDevice"/>
  </bean>
      
  <bean id="recordDevice"
      class="com.habuma.wiring.TapeRecorder"/>
  <bean id="playbackDevice"
      class="com.habuma.wiring.SpeakerPlayback"/>
</beans>


As wired here, I've declared the "recorder" bean to be a simple tape recorder. It records to tape and plays back to a speaker. If I decide later that I need the playback to be over the radio instead a speaker, I just switch the "playbackDevice" bean's class to be "com.habuma.wiring.RadioPlayback". Likewise, I can swap out the "recordDevice" bean's class with "com.habuma.wiring.Mp3Recorder" to record to MP3.


这个东西看起来很好玩,但是我一时还没想到有什么用。大家来探讨一下吧。


这只能说明,设计有问题。把没有关系的两个功能硬是合并到这一个接口中。
0 请登录后投票
论坛首页 Java企业应用版

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