`

IoC != 装配和实例化的反转 != DI(注射依赖)

阅读更多
Inversion of Control(控制反转,IoC)
大家可能已经知道好莱坞(Hollywood)原则
Don’t call us, we’ll call you.
不要找我们,我们会找你。

好莱坞原则在软件开发领域中极受追捧:我们经常把控制逻辑写在其他地方(例如Framework)而非客户化的代码里,我们就更专注于客户化的逻辑,也就是说,外部逻辑负责调用我们客户化的逻辑。在软件开发领域,我们又给它取了一个名字叫控制反转(IoC)[1]。

控制反转概念的涉及面十分广泛,有人认为它是一个模式,但是我更倾向于认为它是一个原则(Principle)。很多模式都实现了控制反转(例如模板方法模式),例如,我们第2章讲解的模板方法模式就是控制反转的一个很好应用,父类的模板方法控制子类的方法调用;还有,使用回调的方法都是控制反转的很好应用。

再如,在Java标准库里,我们常用到查找和排序的这两个方法,binarySearch(…)和sort(…)方法,它们在执行过程中会调用对象的compareTo()方法(如果这些对象实现了java.lang.Comparable接口的话),或者调用我们所传递的回调接口java.util.Comparator对象的compare()方法来比较大小,最终完成查找/排序操作,这些都是控制反转的例子。

此外,我们经常提到的框架(Framework),它最典型的特点其实就是控制反转:框架抽象了通用流程,我们可以通过框架提供的规范(比如子类化抽象类或者实现相关的接口,实现相关的交互协议和接口等等)就可以把客户化的代码植入流程中,完成各种定制的需求。框架和工具库(Library)的区别是:如果框架没有实现控制反转,那么框架就会退化为工具库。也就是说,使用工具库,你必须撰写调用它们的逻辑,每次调用它们都会完成相应的工作,并把控制权返回给调用者;而框架不需要客户程序撰写控制调用的逻辑,由框架专门负责。

以我们时下非常流行的MVC框架Struts为例,我们只需要实现相关的Action,Form类以及相关View,并配置好Action-Form-View的映射关系,这样每次客户端提交请求,该框架都会选择相应的Action去处理它,并根据返回的执行结果选择相应的视图。这些控制逻辑由Struts框架为我们完成了,不需要我们实现如何调用相应Action执行的逻辑,也不需要实现如何选择View显示的逻辑。

IoC和DI(Dependency Injection,依赖注入)
后来,随着轻量级容器/框架不停地涌现,控制反转的概念越来越被开发人员提及,很多轻量级容器/框架标榜使用到的控制反转,其实通过上述介绍我们知道,任何容器/框架都实现了控制反转。它们所说的控制反转指的是对服务/对象/组件的实例化和查找实现了控制反转,这只是控制反转的一种而已。关于这方面的控制反转主要有两种形式:Service Locator(服务定位器)和Dependency Injection(依赖注入,简写为DI),关于这两种形式的讨论,请参见漫谈设计模式第6章

标注
[1] 这个短语首先在Johnson and Foote撰写的论文Designing Reusable Classes使用到。

参考文献:
[1] Martin Fowler. InversionOfControl. Web site: http://martinfowler.com/bliki/InversionOfControl.html. 2005.
[2] Martin Fowler. Inversion of Control Containers and the Dependency Injection pattern. Web site: http://martinfowler.com/articles/injection.html. 2004.
分享到:
评论
35 楼 sunxuetao2010 2011-06-03  
我的理解简单,就是代码都写好,业务的乱七八糟的东西,都不管,最后你要用什么,配置在容器里,它根据你的配置去调用别的对象,配什么,调什么,没有依赖。
34 楼 redhat 2011-06-01  
kakaluyi 写道
redhat 写道
kakaluyi 写道
每个state类持有相同的context的引用,
下面是一个BlueState类,由回调context来实现状态转换(但是状态转换的逻辑封装在context类中,你赞同回调也是控制反转,这边也是回调呀)
public class BlueState extends State{

  public void handlepush(Context c){
     //根据push方法"如果是blue状态的切换到green" ;
     c.setState(new GreenState());

  }
  public void handlepull(Context c){

     //根据pull方法"如果是blue状态的切换到red" ;
    c.setState(new RedState());

  }

  public abstract void getcolor(){ return (Color.blue)}

}


所以我给你指出你的这句话:
引用
状态模式由自己控制状态变化交给了context类
是错的,你把反转的方向搞错了,我给你的回复是:
引用
这个是错误的,刚好相反,如果我们使用if-else/switch-case的话,相当于使用了context控制所有的状态变化逻辑和变化后相应的行为,我们使用状态模式,就是把这二者封装给了状态而不是context,请参见漫谈设计模式和GoF设计模式的状态模式章节。


特别是请理解这句话
引用
我们使用状态模式,就是把这二者封装给了状态而不是context
。修行在个人,看造化了。

引用
),状态的互相转化没有反战控制,可能你在这些模式里做了些变化实现了控制反转,但是一般我们不认为是。

这句话是你说的吧,我只是把反转关系写错了,但是你是把整个概念完全理解错了,算了,感觉你自以为是个牛人,我也自以为是个牛人,到底谁是牛人我都觉得不重要


引用
我只是把反转关系写错了
你写错了让人家明白,这个有点wl了,我说过,]我们不认为是状态模式的实现反转控制的原因很清楚了
引用
要说反转控制,是不严格的,因为状态之间可以不切换的,所以对于状态的设置也未反转到某些state对象里


看完这些,我只是觉得为什么人家facebook才600人,我们动不动就是4000人,还在说,看:我们的成本多低呀。

关于此方面的讨论,如果没有严谨的证据(不明白的时候往往拍脑袋想出来的是歪理,经不起推敲的),我将忽略不再继续。中国很多技术人员觉得自己是大牛,我不是!请大牛们不拿出证据讨论,我只是明白一些oo思想,做过一些实践,和那些精通oo思想的人无法沟通的,记得有位大牛说自己学习20多年,才有那么懂一点,我更是无可比拟,而这位大牛,用mf的话说就是:是为数不多的能够快速构建模型的人!在他老人家眼里,才有几个大牛?当然,我不是把火引向mf,请查阅mf简介和资历再作评价。
33 楼 redhat 2011-06-01  
kakaluyi 写道
redhat 写道
kakaluyi 写道
引用
给你举例说明下,Spring的ORM框架,主要是使用了模板方法模式,使我们更好方便的使用,我们只要把处理查询结果回调交给HibernateTemplate类(或者相应的template)即可,至于什么时间调用你的回调,都交给了这些template类,这即是控制的反转。

我怎么觉得这是门面模式呢,不要看到templete就以为用到了模板模式,模板模式比如servlet提供init,dopost,doget,destroy方法,你可以重写,也可不重写。模板方法是搭好框架由我们继承实现,参考listenr,structs的action。
其他真的关于模式真的有很多不同的见解,不过人是活的,模式只是站在别人的经验上看问题,有争论时正常的。特别是控制反转这种抽象的概念,国外大牛之间都有conflict,不要违反基本原则就好


这个我就不再说明了,以我的观点再看,你没有理解什么是模板方法模式,请参见漫谈设计模式第2章。
目前我没有找到一个人说HibernateTemplate不是使用模板方法模式的,这个请参见spring orm相关的资料,rod大叔的那两本书里应该说明的很清楚了


我们说明问题应该严谨,这也是为什么我常碰见老外讲的技术很严谨,很多人中国人没理解就乱说一气的,我曾经碰见一个人指着模板方法模式说是command模式的,指鹿为马呀!不应该有这种讨论存在的

其实设计模式模式相当复杂的,很多人不可能1-2年对那些基本的23种模式(抛去那些不常用的)完全掌握的,可以说80%以上的只是了解定义和它讲述的故事而已,我碰见很多架构师对模式理解的一塌糊涂的(当然都是中国的架构师,不是自我鄙视中国人),国外很多论坛上,他们所描述的才感觉“英雄所见略同”。

我发现,你是不是不明白控制调用反转才导致理解上的出入。模板方法模式如何实现控制反转的,可以参见gof的设计模式和我的书籍IoC方面的解释(也就是本贴的内容)。

不管有什么争论也好,驴子不是马,这个模式没有使用到IoC就没有使用到,你理解了就会明白它没有使用到还是使用到,目前至少关于这方面争论的话题都没有看到是争论状态模式使用了反转控制的(要说反转控制,是不严格的,因为状态之间可以不切换的,所以对于状态的设置也未反转到某些state对象里),我们应该争论驴子应该拉磨还是应该拖粮食这才有意义。

引用
我们更好方便的使用,我们只要把处理查询结果回调交给HibernateTemplate类(或者相应的template)即可
内部spring hibenatetemple实现确实是实现模板方法,你把我们的使用hibernateTemplate的方式也叫做模板方法我真的怀疑你对模板的理解。

这个是我写给公司同事分享,关于模板方法的
对于用户使用抽象使
定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。
(AbstractClass)角色有如下的责任:


定义并实现了一个模版方法。这个模版方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。

具体模版(ConcreteClass)角色有如下的责任:
实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。

每一个抽象模版角色都可以有任意多个具体模版角色与之对应,而每一个具体模版角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。


引用
你把我们的使用hibernateTemplate的方式也叫做模板方法我真的怀疑你对模板的理解。
这个讨论就再也没有意义了,从哪句话可以看出来我说调用模板方法的方式 是反转控制?
另外,你不理解spring的模板方法模式,不知道你是否知道有一种引入回调的模板方法模式?
关于模板方法模式的讨论我将不再继续,修行在个人。
32 楼 kakaluyi 2011-06-01  
redhat 写道
kakaluyi 写道
每个state类持有相同的context的引用,
下面是一个BlueState类,由回调context来实现状态转换(但是状态转换的逻辑封装在context类中,你赞同回调也是控制反转,这边也是回调呀)
public class BlueState extends State{

  public void handlepush(Context c){
     //根据push方法"如果是blue状态的切换到green" ;
     c.setState(new GreenState());

  }
  public void handlepull(Context c){

     //根据pull方法"如果是blue状态的切换到red" ;
    c.setState(new RedState());

  }

  public abstract void getcolor(){ return (Color.blue)}

}


所以我给你指出你的这句话:
引用
状态模式由自己控制状态变化交给了context类
是错的,你把反转的方向搞错了,我给你的回复是:
引用
这个是错误的,刚好相反,如果我们使用if-else/switch-case的话,相当于使用了context控制所有的状态变化逻辑和变化后相应的行为,我们使用状态模式,就是把这二者封装给了状态而不是context,请参见漫谈设计模式和GoF设计模式的状态模式章节。


特别是请理解这句话
引用
我们使用状态模式,就是把这二者封装给了状态而不是context
。修行在个人,看造化了。

引用
),状态的互相转化没有反战控制,可能你在这些模式里做了些变化实现了控制反转,但是一般我们不认为是。

这句话是你说的吧,我只是把反转关系写错了,但是你是把整个概念完全理解错了,算了,感觉你自以为是个牛人,我也自以为是个牛人,到底谁是牛人我都觉得不重要
31 楼 kakaluyi 2011-06-01  
redhat 写道
kakaluyi 写道
引用
给你举例说明下,Spring的ORM框架,主要是使用了模板方法模式,使我们更好方便的使用,我们只要把处理查询结果回调交给HibernateTemplate类(或者相应的template)即可,至于什么时间调用你的回调,都交给了这些template类,这即是控制的反转。

我怎么觉得这是门面模式呢,不要看到templete就以为用到了模板模式,模板模式比如servlet提供init,dopost,doget,destroy方法,你可以重写,也可不重写。模板方法是搭好框架由我们继承实现,参考listenr,structs的action。
其他真的关于模式真的有很多不同的见解,不过人是活的,模式只是站在别人的经验上看问题,有争论时正常的。特别是控制反转这种抽象的概念,国外大牛之间都有conflict,不要违反基本原则就好


这个我就不再说明了,以我的观点再看,你没有理解什么是模板方法模式,请参见漫谈设计模式第2章。
目前我没有找到一个人说HibernateTemplate不是使用模板方法模式的,这个请参见spring orm相关的资料,rod大叔的那两本书里应该说明的很清楚了


我们说明问题应该严谨,这也是为什么我常碰见老外讲的技术很严谨,很多人中国人没理解就乱说一气的,我曾经碰见一个人指着模板方法模式说是command模式的,指鹿为马呀!不应该有这种讨论存在的

其实设计模式模式相当复杂的,很多人不可能1-2年对那些基本的23种模式(抛去那些不常用的)完全掌握的,可以说80%以上的只是了解定义和它讲述的故事而已,我碰见很多架构师对模式理解的一塌糊涂的(当然都是中国的架构师,不是自我鄙视中国人),国外很多论坛上,他们所描述的才感觉“英雄所见略同”。

我发现,你是不是不明白控制调用反转才导致理解上的出入。模板方法模式如何实现控制反转的,可以参见gof的设计模式和我的书籍IoC方面的解释(也就是本贴的内容)。

不管有什么争论也好,驴子不是马,这个模式没有使用到IoC就没有使用到,你理解了就会明白它没有使用到还是使用到,目前至少关于这方面争论的话题都没有看到是争论状态模式使用了反转控制的(要说反转控制,是不严格的,因为状态之间可以不切换的,所以对于状态的设置也未反转到某些state对象里),我们应该争论驴子应该拉磨还是应该拖粮食这才有意义。

引用
我们更好方便的使用,我们只要把处理查询结果回调交给HibernateTemplate类(或者相应的template)即可
内部spring hibenatetemple实现确实是实现模板方法,你把我们的使用hibernateTemplate的方式也叫做模板方法我真的怀疑你对模板的理解。

这个是我写给公司同事分享,关于模板方法的
对于用户使用抽象使
定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。
(AbstractClass)角色有如下的责任:


定义并实现了一个模版方法。这个模版方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。

具体模版(ConcreteClass)角色有如下的责任:
实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。

每一个抽象模版角色都可以有任意多个具体模版角色与之对应,而每一个具体模版角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。

30 楼 redhat 2011-06-01  
kakaluyi 写道
每个state类持有相同的context的引用,
下面是一个BlueState类,由回调context来实现状态转换(但是状态转换的逻辑封装在context类中,你赞同回调也是控制反转,这边也是回调呀)
public class BlueState extends State{

  public void handlepush(Context c){
     //根据push方法"如果是blue状态的切换到green" ;
     c.setState(new GreenState());

  }
  public void handlepull(Context c){

     //根据pull方法"如果是blue状态的切换到red" ;
    c.setState(new RedState());

  }

  public abstract void getcolor(){ return (Color.blue)}

}


所以我给你指出你的这句话:
引用
状态模式由自己控制状态变化交给了context类
是错的,你把反转的方向搞错了,我给你的回复是:
引用
这个是错误的,刚好相反,如果我们使用if-else/switch-case的话,相当于使用了context控制所有的状态变化逻辑和变化后相应的行为,我们使用状态模式,就是把这二者封装给了状态而不是context,请参见漫谈设计模式和GoF设计模式的状态模式章节。


特别是请理解这句话
引用
我们使用状态模式,就是把这二者封装给了状态而不是context
。修行在个人,看造化了。
29 楼 redhat 2011-06-01  
kakaluyi 写道
引用
给你举例说明下,Spring的ORM框架,主要是使用了模板方法模式,使我们更好方便的使用,我们只要把处理查询结果回调交给HibernateTemplate类(或者相应的template)即可,至于什么时间调用你的回调,都交给了这些template类,这即是控制的反转。

我怎么觉得这是门面模式呢,不要看到templete就以为用到了模板模式,模板模式比如servlet提供init,dopost,doget,destroy方法,你可以重写,也可不重写。模板方法是搭好框架由我们继承实现,参考listenr,structs的action。
其他真的关于模式真的有很多不同的见解,不过人是活的,模式只是站在别人的经验上看问题,有争论时正常的。特别是控制反转这种抽象的概念,国外大牛之间都有conflict,不要违反基本原则就好


这个我就不再说明了,以我的观点再看,你没有理解什么是模板方法模式,请参见漫谈设计模式第2章。
目前我没有找到一个人说HibernateTemplate不是使用模板方法模式的,这个请参见spring orm相关的资料,rod大叔的那两本书里应该说明的很清楚了


我们说明问题应该严谨,这也是为什么我常碰见老外讲的技术很严谨,很多人中国人没理解就乱说一气的,我曾经碰见一个人指着模板方法模式说是command模式的,指鹿为马呀!不应该有这种讨论存在的

其实设计模式模式相当复杂的,很多人不可能1-2年对那些基本的23种模式(抛去那些不常用的)完全掌握的,可以说80%以上的只是了解定义和它讲述的故事而已,我碰见很多架构师对模式理解的一塌糊涂的(当然都是中国的架构师,不是自我鄙视中国人),国外很多论坛上,他们所描述的才感觉“英雄所见略同”。

我发现,你是不是不明白控制调用反转才导致理解上的出入。模板方法模式如何实现控制反转的,可以参见gof的设计模式和我的书籍IoC方面的解释(也就是本贴的内容)。

不管有什么争论也好,驴子不是马,这个模式没有使用到IoC就没有使用到,你理解了就会明白它没有使用到还是使用到,目前至少关于这方面争论的话题都没有看到是争论状态模式使用了反转控制的(要说反转控制,是不严格的,因为状态之间可以不切换的,所以对于状态的设置也未反转到某些state对象里),我们应该争论驴子应该拉磨还是应该拖粮食这才有意义。
28 楼 kakaluyi 2011-06-01  
每个state类持有相同的context的引用,
下面是一个BlueState类,由回调context来实现状态转换(但是状态转换的逻辑封装在context类中,你赞同回调也是控制反转,这边也是回调呀)
public class BlueState extends State{

  public void handlepush(Context c){
     //根据push方法"如果是blue状态的切换到green" ;
     c.setState(new GreenState());

  }
  public void handlepull(Context c){

     //根据pull方法"如果是blue状态的切换到red" ;
    c.setState(new RedState());

  }

  public abstract void getcolor(){ return (Color.blue)}

}

27 楼 redhat 2011-06-01  
<div class="quote_title">kakaluyi 写道</div>
<div class="quote_div">
<pre name="code" class="java">状态模式
public class Context{

  private Sate state=null; //我们将原来的 Color state 改成了新建的State state;

  //setState是用来改变state的状态 使用setState实现状态的切换
  pulic void setState(State state){

    this.state=state;

  }

  public void push(){

    //状态的切换的细节部分,在本例中是颜色的变化,已经封装在子类的handlepush中实现,这里无需关心
    state.handlepush(this);
    
    //因为sample要使用state中的一个切换结果,使用getColor()
    Sample sample=new Sample(state.getColor());
    sample.operate();

  }



  public void pull(){

    state.handlepull(this);
    
    Sample2 sample2=new Sample2(state.getColor());
    sample2.operate();

  }

}

</pre>
<p>状态模式一定要有context类来封装变化逻辑, 由context类实现状态的变化,状态模式不是控制反转吗?这个我们的理解出入很大</p>
</div>
<p>bean有setter方法的,但是调用setter的方法逻辑我们是 放在外部程序的,这叫反转控制。context设置状态的变化方法是在context里的,调用控制在外面。这个请你参看/搜索相关文献理解完整的重要。</p>
26 楼 kakaluyi 2011-06-01  
引用
给你举例说明下,Spring的ORM框架,主要是使用了模板方法模式,使我们更好方便的使用,我们只要把处理查询结果回调交给HibernateTemplate类(或者相应的template)即可,至于什么时间调用你的回调,都交给了这些template类,这即是控制的反转。

我怎么觉得这是门面模式呢,不要看到templete就以为用到了模板模式,模板模式比如servlet提供init,dopost,doget,destroy方法,你可以重写,也可不重写。模板方法是搭好框架由我们继承实现,参考listenr,structs的action。
其他真的关于模式真的有很多不同的见解,不过人是活的,模式只是站在别人的经验上看问题,有争论时正常的。特别是控制反转这种抽象的概念,国外大牛之间都有conflict,不要违反基本原则就好
25 楼 kakaluyi 2011-06-01  
<pre name="code" class="java">状态模式
public class Context{

  private Sate state=null; //我们将原来的 Color state 改成了新建的State state;

  //setState是用来改变state的状态 使用setState实现状态的切换
  pulic void setState(State state){

    this.state=state;

  }

  public void push(){

    //状态的切换的细节部分,在本例中是颜色的变化,已经封装在子类的handlepush中实现,这里无需关心
    state.handlepush(this);
    
    //因为sample要使用state中的一个切换结果,使用getColor()
    Sample sample=new Sample(state.getColor());
    sample.operate();

  }



  public void pull(){

    state.handlepull(this);
    
    Sample2 sample2=new Sample2(state.getColor());
    sample2.operate();

  }

}

</pre>
<p>状态模式一定要有context类来封装变化逻辑, 由context类实现状态的变化,状态模式不是控制反转吗?这个我们的理解出入很大</p>
24 楼 redhat 2011-05-31  
[quote=&quot;kakaluyi&quot;]
[quote=&quot;redhat&quot;]
[quote=&quot;kakaluyi&quot;]控制反转是一种编程思想,可以引申出很多模式,比如一个对象a持有另一个对象b的引用,
1 当对象a更新的时候,通知b对象回调某些方法  (观察者模式)
2 b的状态由a对象来维护(状态模式)
3 控制反转还可以避免代码污染,减少耦合,比如:a和b对象互相持有对方引用.
4 工厂模式(由子类决定创建的具体对象)
Factory a=new FactoryImp1()
ojbect1=a.create();
Factory b=new FactoryImp2()
object2=b.create();
这样a和b是可以插拔替换的,完全由子类来实现控制创建,也可以说是控制反转。
5 Spring的控制反转,由spring工厂读取xml帮你注入某个类需要的对象
等等等等,和“只和陌生人说话”,“迪米特法则”,“开闭原则”,等作为开发高弹性,高可扩展,高可维护代码的必要法则。



刚看到这个回复,
引用

工厂模式(由子类决定创建的具体对象)b的状态由a对象来维护(状态模式)
这两个例子不确切,其实前者你举的这个例子比较明确的是指它实现了封装(隐藏了实现,使用了多态),状态的互相转化没有反战控制,可能你在这些模式里做了些变化实现了控制反转,但是一般我们不认为是。
回答:工厂模式对于实例的创建由父类反转延迟到了子类,状态模式由自己控制状态变化交给了context类,包括门面模式由统一的门面类来封装变化,我觉得这些都可以算是控制反转。

控制反转,我们认为是一个原则


引用
编程思想



不够确切,和你后面  回答:我认为控制反转是一个思想而不是原则(原则中文意思:观察问题、处理问题的准则,很显然,在遇到a+b=c这种简单程序逻辑的情况下,是没必要过度设计,应用控制反转,所以这边最好不要用原则)。由这个思想衍生了很多模式,我也不赞同控制反转是模式,我第一句话就摆在那边,看了你两个回复,我都觉得你没看懂我也认为控制反转不是模式


引用
和“只和陌生人说话”,“迪米特法则”,“开闭原则”,等作为开发高弹性,高可扩展,高可维护代码的必要法则



一个道理。
说spring的反转控制,spring包含很多框架,我前述讲了,任何框架都是实现了反转控制,否则会退化工具库。回答:这个同意,这就是框架存在的意义,如果什么事都要我们自己干,框架用来做什么呢

1.抽象工厂的子类的延时决定,这在面向对象编程里,主要是抽象和封装二者的特点,请参见Java编程思想的抽象,和设计模式精解关于封装的论述,并请参见GoF在设计模式一书关于工厂模式以及讲解模式之前做铺垫的章节关于封装和接口/封装的论述。如果抽象工厂类的父类没有逻辑控制抽象工厂子类的逻辑,那么就不是反转控制,如果你结合了模板方法模式,把它运用在工厂模式,那就使用了反转控制,但功劳还是模板方法模式的。

2.反转控制是原则,这个比较确切,说成思想有点过,我们有面向对象的编程思想,还没有IoC编程思想,觉得国人对一些稍微复杂一点的理论就套用思想,原则,理论,这个还是得和老外学学,要客观,请参见wikipedia的Inversion of control,还有专门讨论IoC一个大学论坛我忘掉了,那里写的也比较详细,认为IoC是原则,不是模式,你可以上google搜下。而Martin Fowler认为是模式,这里我就不再讨论。

你可以找出思想和原则的区别,但是中文的思想还是英文里的思想,都是和想法这个概念相差甚远,principle在英文里的含义是:a law, a rule or a theory,请参见http://www.google.com.hk/dictionary?langpair=en|en&amp;q=principle&amp;hl=zh-CN&amp;aq=f,用作原则来说,还是相当确切的,中文含义这里便不再多说了,翻译始终是翻译。

3.由spring工厂读取xml帮你注入某个类需要的对象这个不是spring的bean框架的实现IoC的本质,和读取xml没有任何关系(annotation,或者你直接调用setter都可以),spring的bean框架作为bean容器,为组装对象的反转主要体现在(不说annotation等注入),我总结的setter方法注入,constructor注入(还有其他形式的注入,高级用法),而xml起到的只是配置的作用,而就是说,spring使用beanClass.newInstance();之后,setterMethod.invoke(bean,dependentBean)(其实就是bean.setdependentBean(dependentBean)),这句才是使用setter方法组装bean的真正逻辑,也是说明它是反转控制框架的证据。你在测试时,注入mock的denpendentBean,这就是反转控制,并不是非的是框架,我想你也应该认同。

MF对于IoC中对于框架讨论请参见http://www.martinfowler.com/articles/injection.html,http://martinfowler.com/bliki/InversionOfControl.html,特别是第一篇。

给你举例说明下,Spring的ORM框架,主要是使用了模板方法模式,使我们更好方便的使用,我们只要把处理查询结果回调交给HibernateTemplate类(或者相应的template)即可,至于什么时间调用你的回调,都交给了这些template类,这即是控制的反转。


4.
引用
状态模式由自己控制状态变化交给了context类

,这个是错误的,刚好相反,如果我们使用if-else/switch-case的话,相当于使用了context控制所有的状态变化逻辑和变化后相应的行为,我们使用状态模式,就是把这二者封装给了状态而不是context,请参见漫谈设计模式和GoF设计模式的状态模式章节。

5.
引用
门面模式由统一的门面类来封装变化,我觉得这些都可以算是控制反转

一般性的facade模式,也不是控制反转,控制反转不能认为是门面使用了子系统对象,那就是控制反转,如果这样认为的话,client对象使用服务对象都算是了。
控制反转强调控制逻辑,而且这些控制逻辑反转,交给非使用/实现的对象。所以你说的回调,观察者模式是控制反转,理解非常到位,目前大家都是公认的。

关于其中有些模式你认为实现了反转控制的,请给出相关出处和引文,好便大家一起探讨,但不管这样,希望都是严谨的,经得起时间考验的。

我这里写的都是大家比较公认的概念,没有创造自己的概念,没有有创造的概念,如果有,会给出确切的含义,以及必要的证明(需要的话,概念不等同于定理。

你讨论的这些都很好,很深入,我觉得此贴应该成为精华帖。

23 楼 kakaluyi 2011-05-31  
<div class="quote_title">redhat 写道</div>
<div class="quote_div">
<div class="quote_title">kakaluyi 写道</div>
<div class="quote_div">控制反转是一种编程思想,可以引申出很多模式,比如一个对象a持有另一个对象b的引用, <br>1 当对象a更新的时候,通知b对象回调某些方法  (观察者模式) <br>2 b的状态由a对象来维护(状态模式) <br>3 控制反转还可以避免代码污染,减少耦合,比如:a和b对象互相持有对方引用. <br>4 工厂模式(由子类决定创建的具体对象) <br>Factory a=new FactoryImp1() <br>ojbect1=a.create(); <br>Factory b=new FactoryImp2() <br>object2=b.create(); <br>这样a和b是可以插拔替换的,完全由子类来实现控制创建,也可以说是控制反转。 <br>5 Spring的控制反转,由spring工厂读取xml帮你注入某个类需要的对象 <br>等等等等,和“只和陌生人说话”,“迪米特法则”,“开闭原则”,等作为开发高弹性,高可扩展,高可维护代码的必要法则。</div>
<br><br><br>刚看到这个回复,
<div class="quote_title">引用</div>
<div class="quote_div">
<strong>工厂模式(由子类决定创建的具体对象)</strong>和 <strong>b的状态由a对象来维护(状态模式)</strong> </div>
这两个例子不确切,其实前者你举的这个例子比较明确的是指它实现了封装(隐藏了实现,使用了多态),状态的互相转化没有反战控制,<strong>可能你在这些模式里做了些变化实现了控制反转</strong>,但是一般我们不认为是。 <br><span style="color: #ff0000;">回答:工厂模式对于实例的创建由父类反转延迟到了子类,状态模式由自己控制状态变化交给了context类,包括门面模式由统一的门面类来封装变化,我觉得这些都可以算是控制反转。</span><br><br>控制反转,我们认为是一个<strong>原则</strong>,
<div class="quote_title">引用</div>
<div class="quote_div">编程思想</div>
不够确切,和你后面  回答:<span style="color: #ff0000;">我认为</span><span style="color: #ff0000;">控制反转是一个思想而不是原则(原则中文意思:<span style="color: #000000;"><strong>观察问题、处理问题的准则</strong>,<span style="color: #ff0000;">很显然</span>,</span><span style="color: #ff0000;">在遇到a+b=c这种简单程序逻辑的情况下,是没必要过度设计,应用控制反转,所以这边最好不要用原则</span>)。由这个思想衍生了很多模式,我也不赞同控制反转是模式,我第一句话就摆在那边,看了你两个回复,我都觉得你没看懂我也认为控制反转不是模式</span>
<div class="quote_title">引用</div>
<div class="quote_div">和“只和陌生人说话”,“迪米特法则”,“开闭原则”,等作为开发高弹性,高可扩展,高可维护代码的必要法则</div>
一个道理。 <br>说spring的反转控制,spring包含很多框架,我前述讲了,<strong>任何框架</strong>都是实现了反转控制,否则会退化工具库。<span style="color: #ff0000;">回答:</span><span style="color: #ff0000;">这个同意,这就是框架存在的意义,如果什么事都要我们自己干,框架用来做什么呢</span><br>
</div>
<p> </p>
22 楼 redhat 2011-05-30  
kakaluyi 写道
控制反转是一种编程思想,可以引申出很多模式,比如一个对象a持有另一个对象b的引用,
1 当对象a更新的时候,通知b对象回调某些方法  (观察者模式)
2 b的状态由a对象来维护(状态模式)
3 控制反转还可以避免代码污染,减少耦合,比如:a和b对象互相持有对方引用.
4 工厂模式(由子类决定创建的具体对象)
Factory a=new FactoryImp1()
ojbect1=a.create();
Factory b=new FactoryImp2()
object2=b.create();
这样a和b是可以插拔替换的,完全由子类来实现控制创建,也可以说是控制反转。
5 Spring的控制反转,由spring工厂读取xml帮你注入某个类需要的对象
等等等等,和“只和陌生人说话”,“迪米特法则”,“开闭原则”,等作为开发高弹性,高可扩展,高可维护代码的必要法则。



刚看到这个回复,
引用
工厂模式(由子类决定创建的具体对象)b的状态由a对象来维护(状态模式)
这两个例子不确切,其实前者你举的这个例子比较明确的是指它实现了封装(隐藏了实现,使用了多态),状态的互相转化没有反战控制,可能你在这些模式里做了些变化实现了控制反转,但是一般我们不认为是。


控制反转,我们认为是一个原则
引用
编程思想
不够确切,和你后面
引用
和“只和陌生人说话”,“迪米特法则”,“开闭原则”,等作为开发高弹性,高可扩展,高可维护代码的必要法则
一个道理。
说spring的反转控制,spring包含很多框架,我前述讲了,任何框架都是实现了反转控制,否则会退化工具库。
21 楼 gudgudstudy 2011-05-29  
说的很好,领教了!
20 楼 JE帐号 2011-05-19  
redhat 写道
JE帐号 写道
redhat 写道
JE帐号 写道
redhat 写道
JE帐号 写道
我一直觉得"控制反转"这个词还是有些抽象.

几乎每次看到对IOC解释都是这样,一大段话,左一个例子,右一个例子,这是IOC,那也是IOC.总觉得这些描述不是属于那种一说出来,大家就恍然大悟的那种话,而是给解释,举例.


这个名字是最好的给这个概念的名字,把对程序的某些控制权交给其他外部程序来控制,即控制反转。



我想你的回答恰恰直接说明了我对"控制反转"的不满.
"对程序的某些控制权交给其他外部程序",到底是哪些?

并不是说"控制反转"不对,仅仅是觉得不足够好,没有那种一眼看传的感觉.

要说我,"IOC体现的理念在于,仅仅去使用一个对象,而不需要去关注这个对象如何来的"这句话可能更揭示IOC的本质一些.




兄弟,你要你仔细看看题目,你就知道:
引用
"IOC体现的理念在于,仅仅去使用一个对象,而不需要去关注这个对象如何来的"
是个谬误,我专门纠正这个错误来写这篇文档,所以我说你还不太明白IoC的概念来说这个名字有问题。
mf怕大家搞混,准们写了两篇博文说明这个问题,相信写那些书的人和看这些博文的人都看过,但是还是不理解他老人家的意思,IoC的最初出处我都给了地址,你慢慢看吧。



我看了你的题目了,事实上你blog的文章我很早前就看过了.所以,我不是在反对你的观点,但是问题的关键在于,你要去证明它.

你的观点"IoC != 装配和实例化的反转",我对此很感兴趣,因为就像我说的,我的理解中IoC重点反映的思想就是装配和实例化的反转,现在看到您这样不同的观点,我并不想去反对,而是希望可以看到一些有逻辑性的证明,这些证明可以让我改变观点,对于我个人也是一种进步.但是就我所理解的,我并没有看到这样的证明.

说句实话,MF 05年那篇文章,上来举了两段代码例子,我看来看去,第二段就是比第一段多了实例和装配,倒又是在一定程度上加强了我原先的观点... ...

再补充一下我的理解,IOC概念的出现一定程度上与接口概念类似.由于接口的简洁性,声明性,使得我们可以把注意力转到接口行为上,以及对这种行为能力的使用上,而不去考虑实例化问题.IOC也类似如此,他解放了我们实例化和装配的工作,从而让我们把注意力更多的集中到对象的使用上.不同的是接口是语言层面的支持,而IOC一般是FrameWork层面的支持.


我明白你的意思是说IOC所反映的思想范畴不仅仅包括简单的"装配和实例化的反转",他有更多的内涵.但是从文章我没看到对这一观点更实质的论证. 你不能说句"相信写那些书的人和看这些博文的人都看过,但是还是不理解他老人家的意思"就算了,而是需要去论证它


我不知道为什么需要证明?因为这个是我们目前公认归纳的概念,但是很多人搞不明白这个概念。我这里做的是个传教士的角色,讨论这个概念是什么。
mf在http://martinfowler.com/bliki/InversionOfControl.html专门讲解什么是IoC,很多人不知道IoC出自哪里就开始给大家讲解,结果全解释错另外。
mf在http://martinfowler.com/articles/injection.html一文的Inversion of Control一节,指出
引用
Inversion of control is a common characteristic of frameworks, so saying that these lightweight containers are special because they use inversion of control is like saying my car is special because it has wheels.

引用
The question, is what aspect of control are they inverting?
后面举了一个例子,讲解他开始遇见这个概念是,自己使用到一个框架,这个框架
引用
UI framework would contain this main loop
,把这个控制反转到框架了,这样,
引用
your program instead provided event handlers for the various fields on the screen
就可以了,不需要写这一个loop来做了。

这里为此写篇文章再次说明,其实要看大家造化了,mf讲解的我自认为很清楚了,但是还有人弄错,我归结为语言的问题(大家很懒,不愿意阅读英文章,喜欢中文,毕竟是习惯),但是现在开来,好像有可能不是这个原因,希望参与讨论者能够仔细阅读完这两篇论文在做讨论,举出什么地方有误。



... ... ...
-------------------------------
为什么需要证明.
传教士.
看大家造化了.
我自认为很清楚了.
-------------------------------
... ... ...




19 楼 redhat 2011-05-19  
JE帐号 写道
redhat 写道
JE帐号 写道
redhat 写道
JE帐号 写道
我一直觉得"控制反转"这个词还是有些抽象.

几乎每次看到对IOC解释都是这样,一大段话,左一个例子,右一个例子,这是IOC,那也是IOC.总觉得这些描述不是属于那种一说出来,大家就恍然大悟的那种话,而是给解释,举例.


这个名字是最好的给这个概念的名字,把对程序的某些控制权交给其他外部程序来控制,即控制反转。



我想你的回答恰恰直接说明了我对"控制反转"的不满.
"对程序的某些控制权交给其他外部程序",到底是哪些?

并不是说"控制反转"不对,仅仅是觉得不足够好,没有那种一眼看传的感觉.

要说我,"IOC体现的理念在于,仅仅去使用一个对象,而不需要去关注这个对象如何来的"这句话可能更揭示IOC的本质一些.




兄弟,你要你仔细看看题目,你就知道:
引用
"IOC体现的理念在于,仅仅去使用一个对象,而不需要去关注这个对象如何来的"
是个谬误,我专门纠正这个错误来写这篇文档,所以我说你还不太明白IoC的概念来说这个名字有问题。
mf怕大家搞混,准们写了两篇博文说明这个问题,相信写那些书的人和看这些博文的人都看过,但是还是不理解他老人家的意思,IoC的最初出处我都给了地址,你慢慢看吧。



我看了你的题目了,事实上你blog的文章我很早前就看过了.所以,我不是在反对你的观点,但是问题的关键在于,你要去证明它.

你的观点"IoC != 装配和实例化的反转",我对此很感兴趣,因为就像我说的,我的理解中IoC重点反映的思想就是装配和实例化的反转,现在看到您这样不同的观点,我并不想去反对,而是希望可以看到一些有逻辑性的证明,这些证明可以让我改变观点,对于我个人也是一种进步.但是就我所理解的,我并没有看到这样的证明.

说句实话,MF 05年那篇文章,上来举了两段代码例子,我看来看去,第二段就是比第一段多了实例和装配,倒又是在一定程度上加强了我原先的观点... ...

再补充一下我的理解,IOC概念的出现一定程度上与接口概念类似.由于接口的简洁性,声明性,使得我们可以把注意力转到接口行为上,以及对这种行为能力的使用上,而不去考虑实例化问题.IOC也类似如此,他解放了我们实例化和装配的工作,从而让我们把注意力更多的集中到对象的使用上.不同的是接口是语言层面的支持,而IOC一般是FrameWork层面的支持.


我明白你的意思是说IOC所反映的思想范畴不仅仅包括简单的"装配和实例化的反转",他有更多的内涵.但是从文章我没看到对这一观点更实质的论证. 你不能说句"相信写那些书的人和看这些博文的人都看过,但是还是不理解他老人家的意思"就算了,而是需要去论证它


我不知道为什么需要证明?因为这个是我们目前公认归纳的概念,但是很多人搞不明白这个概念。我这里做的是个传教士的角色,讨论这个概念是什么。
mf在http://martinfowler.com/bliki/InversionOfControl.html专门讲解什么是IoC,很多人不知道IoC出自哪里就开始给大家讲解,结果全解释错另外。
mf在http://martinfowler.com/articles/injection.html一文的Inversion of Control一节,指出
引用
Inversion of control is a common characteristic of frameworks, so saying that these lightweight containers are special because they use inversion of control is like saying my car is special because it has wheels.

引用
The question, is what aspect of control are they inverting?
后面举了一个例子,讲解他开始遇见这个概念是,自己使用到一个框架,这个框架
引用
UI framework would contain this main loop
,把这个控制反转到框架了,这样,
引用
your program instead provided event handlers for the various fields on the screen
就可以了,不需要写这一个loop来做了。

这里为此写篇文章再次说明,其实要看大家造化了,mf讲解的我自认为很清楚了,但是还有人弄错,我归结为语言的问题(大家很懒,不愿意阅读英文章,喜欢中文,毕竟是习惯),但是现在开来,好像有可能不是这个原因,希望参与讨论者能够仔细阅读完这两篇论文在做讨论,举出什么地方有误。

18 楼 JE帐号 2011-05-19  
redhat 写道
JE帐号 写道
redhat 写道
JE帐号 写道
我一直觉得"控制反转"这个词还是有些抽象.

几乎每次看到对IOC解释都是这样,一大段话,左一个例子,右一个例子,这是IOC,那也是IOC.总觉得这些描述不是属于那种一说出来,大家就恍然大悟的那种话,而是给解释,举例.


这个名字是最好的给这个概念的名字,把对程序的某些控制权交给其他外部程序来控制,即控制反转。



我想你的回答恰恰直接说明了我对"控制反转"的不满.
"对程序的某些控制权交给其他外部程序",到底是哪些?

并不是说"控制反转"不对,仅仅是觉得不足够好,没有那种一眼看传的感觉.

要说我,"IOC体现的理念在于,仅仅去使用一个对象,而不需要去关注这个对象如何来的"这句话可能更揭示IOC的本质一些.




兄弟,你要你仔细看看题目,你就知道:
引用
"IOC体现的理念在于,仅仅去使用一个对象,而不需要去关注这个对象如何来的"
是个谬误,我专门纠正这个错误来写这篇文档,所以我说你还不太明白IoC的概念来说这个名字有问题。
mf怕大家搞混,准们写了两篇博文说明这个问题,相信写那些书的人和看这些博文的人都看过,但是还是不理解他老人家的意思,IoC的最初出处我都给了地址,你慢慢看吧。



我看了你的题目了,事实上你blog的文章我很早前就看过了.所以,我不是在反对你的观点,但是问题的关键在于,你要去证明它.

你的观点"IoC != 装配和实例化的反转",我对此很感兴趣,因为就像我说的,我的理解中IoC重点反映的思想就是装配和实例化的反转,现在看到您这样不同的观点,我并不想去反对,而是希望可以看到一些有逻辑性的证明,这些证明可以让我改变观点,对于我个人也是一种进步.但是就我所理解的,我并没有看到这样的证明.

说句实话,MF 05年那篇文章,上来举了两段代码例子,我看来看去,第二段就是比第一段多了实例和装配,倒又是在一定程度上加强了我原先的观点... ...

再补充一下我的理解,IOC概念的出现一定程度上与接口概念类似.由于接口的简洁性,声明性,使得我们可以把注意力转到接口行为上,以及对这种行为能力的使用上,而不去考虑实例化问题.IOC也类似如此,他解放了我们实例化和装配的工作,从而让我们把注意力更多的集中到对象的使用上.不同的是接口是语言层面的支持,而IOC一般是FrameWork层面的支持.


我明白你的意思是说IOC所反映的思想范畴不仅仅包括简单的"装配和实例化的反转",他有更多的内涵.但是从文章我没看到对这一观点更实质的论证. 你不能说句"相信写那些书的人和看这些博文的人都看过,但是还是不理解他老人家的意思"就算了,而是需要去论证它








17 楼 redhat 2011-05-19  
smallsnake 写道
两者没有什么太多区别

DI,依赖倒置,就是一个抽象工厂模式:通过对象的组合,关联一群客户逻辑,以达到逻辑解耦


16 楼 smallsnake 2011-05-19  
两者没有什么太多区别

DI,依赖倒置,就是一个抽象工厂模式:通过对象的组合,关联一群客户逻辑,以达到逻辑解耦

相关推荐

Global site tag (gtag.js) - Google Analytics