﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-ChenGen-文章分类-spring</title><link>http://www.blogjava.net/ChenGen/category/21506.html</link><description>无宁静无以致远 非淡薄无以明志</description><language>zh-cn</language><lastBuildDate>Tue, 10 Apr 2007 09:45:49 GMT</lastBuildDate><pubDate>Tue, 10 Apr 2007 09:45:49 GMT</pubDate><ttl>60</ttl><item><title>控制反转(Inverssion of Control,IoC)</title><link>http://www.blogjava.net/ChenGen/articles/109660.html</link><dc:creator>ChenGen</dc:creator><author>ChenGen</author><pubDate>Tue, 10 Apr 2007 07:50:00 GMT</pubDate><guid>http://www.blogjava.net/ChenGen/articles/109660.html</guid><wfw:comment>http://www.blogjava.net/ChenGen/comments/109660.html</wfw:comment><comments>http://www.blogjava.net/ChenGen/articles/109660.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ChenGen/comments/commentRss/109660.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ChenGen/services/trackbacks/109660.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;"><span style="font-family: Courier;">作者：Martin Fowler</span><br style="font-family: Courier;"><span style="font-family: Courier;">原文地址：http://martinfowler.com/bliki/InversionOfControl.html
</span><br style="font-family: Courier;"><br style="font-family: Courier;">
<p style="font-family: Courier;">在扩展框架的时候，我们常常会遇到&#8220;控制反转&#8221;这个现象，确实，它很多时候都被用来定义框架的特性。</p>
<p style="font-family: Courier;">
现在我们来考虑一个简单的例子，假设我在写一个通过命令行的方式从用户那里获取信息的程序，我的程序会这样写：</p>
<pre style="font-family: Courier;">  #ruby<br>  puts 'What is your name?'<br>  name = gets<br>  process_name(name)<br>  puts 'What is your quest?'<br>  quest = gets<br>  process_quest(quest)</pre>
<p style="font-family: Courier;">
在交互的过程中，我的程序处于控制状态：它决定何时问问题、何时给出回应、何时处理结果。</p>
<p style="font-family: Courier;">然而，如果我通过窗口的方式来做，那么我会通过配置窗口来实现：</p>
<pre style="font-family: Courier;">  require 'tk'<br>  root = TkRoot.new()<br>  name_label = TkLabel.new() {text "What is Your Name?"}<br>  name_label.pack<br>  name = TkEntry.new(root).pack<br>  name.bind("FocusOut") {process_name(name)}<br>  quest_label = TkLabel.new() {text "What is Your Quest?"}<br>  quest_label.pack<br>  quest = TkEntry.new(root).pack<br>  quest.bind("FocusOut") {process_quest(quest)}<br>  Tk.mainloop()</pre>
<p style="font-family: Courier;">
在控制流程上，这两个程序有很大的不同，尤其在控制方法 process_name 和 process_quest 的调用上。在命令行的形式中，我的程序决定何时调用这些方法；而在使用窗口的例子中，则不是由我的程序来决定，我把控制交给了窗口系统（通过 Tk.mainloop 命令）。窗口系统基于我在创建窗口时所作的绑定来决定何时调用那些方法，所以控制被反转了—不是有我的程序来调用窗口，而是由窗口来调用我的程序—这中现象就叫做&#8220;控制反转&#8221;。</p>
<p><span style="font-family: Courier; font-style: italic;">框架的一个很重要的特性就是，用户定义方法常常由框架自身来调用，而不是由用户的代码来调用。框架常常扮演主程序的角色来协调应用程序的活动。这种控制反转是框架成为一个强大的可以扩展的骨架。用户提供的方法对框架提供的一般性算法进行裁剪来提供更特殊的应用。</span><em style="font-family: Courier; font-style: italic;">--<a href="http://www.laputan.org/drc/drc.html">Ralph Johnson and Brian Foote</a></em><span style="font-family: Courier;">
</span></p>
<p><span style="font-family: Courier;">控制反转是使框架不同于库的一个关键的部分。库在本质上是一系列你可以调用的方法，现在一般组织成类的形式，每次调用都会完成一些工作，然后将控制权返回给调用者。</span></p>
<p><span style="font-family: Courier;">框架内部嵌套了一些抽象的设计，有很多内建表现。为了使用它，你需要通过继承或者插件的方式将你的程序插入到框架的一些位置，然后框架会在这些地方调用你的代码。</span></p>
<p><span style="font-family: Courier;">有多种方法向框架插入你需要被调用的代码。在上面的例子中，我们通过在在文本框上调用 bind 方法，同时将消息名称作为参数传给它，后面再跟一个用&#8220;{}&#8221;括起来的方法，来向框架插入代码。当文本框检测到一个消息的时候，就会调用在&#8220;{}&#8221;中的方法。使用&#8220;{}&#8221;是一中很方便的方式，但是很多编程语言都不支持这中方式。</span></p>
<p><span style="font-family: Courier;">另一种方法是框架定义一些消息，然后在用户代码中注册这些消息。.NET就是这样一个平台，它在语言方面拥有这样的特性，可以让用户在窗口上定义一些消息，然后可以将方法绑定到这些消息上。</span></p>
<p><span style="font-family: Courier;">上面的这些方法（他们实际上是相同的）在单个case上面工作得很好，但是有时候需要在单个单元扩展上面绑定多个方法的调用，在这种情况下，框架可以定义一个接口，用户代码通过实现这个接口来实现相关的调用。（这段话我也似懂非懂）</span></p>
<p><span style="font-family: Courier;">EJBs是这种形式的控制反转的一个很好的例子。当你在开发一个 session bean 的时候，你可以实现多个在不同生命周期点上被 EJB 容器调用的方法。例如，一个 Session Bean 接口定义了 ejbRemove、ejbPassivate和ejbActivate。你不需要关心这些方法什么时候被调用，而只需要关心它们做些什么。由容器来调用用户的程序，而不是用户的程序来调用容器。</span></p>
</span>  <img src ="http://www.blogjava.net/ChenGen/aggbug/109660.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ChenGen/" target="_blank">ChenGen</a> 2007-04-10 15:50 <a href="http://www.blogjava.net/ChenGen/articles/109660.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>