精华帖 (1) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (8)
|
|
---|---|
作者 | 正文 |
发表时间: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讲解的我自认为很清楚了,但是还有人弄错,我归结为语言的问题(大家很懒,不愿意阅读英文章,喜欢中文,毕竟是习惯),但是现在开来,好像有可能不是这个原因,希望参与讨论者能够仔细阅读完这两篇论文在做讨论,举出什么地方有误。 ... ... ... ------------------------------- 为什么需要证明. 传教士. 看大家造化了. 我自认为很清楚了. ------------------------------- ... ... ... |
|
返回顶楼 | |
发表时间:2011-05-29
说的很好,领教了!
|
|
返回顶楼 | |
发表时间: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包含很多框架,我前述讲了,任何框架都是实现了反转控制,否则会退化工具库。 |
|
返回顶楼 | |
发表时间:2011-05-31
最后修改:2011-05-31
redhat 写道
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对象来维护(状态模式)
这两个例子不确切,其实前者你举的这个例子比较明确的是指它实现了封装(隐藏了实现,使用了多态),状态的互相转化没有反战控制,可能你在这些模式里做了些变化实现了控制反转,但是一般我们不认为是。 回答:工厂模式对于实例的创建由父类反转延迟到了子类,状态模式由自己控制状态变化交给了context类,包括门面模式由统一的门面类来封装变化,我觉得这些都可以算是控制反转。 控制反转,我们认为是一个原则, 引用
编程思想
不够确切,和你后面 回答:我认为控制反转是一个思想而不是原则(原则中文意思:观察问题、处理问题的准则,很显然,在遇到a+b=c这种简单程序逻辑的情况下,是没必要过度设计,应用控制反转,所以这边最好不要用原则)。由这个思想衍生了很多模式,我也不赞同控制反转是模式,我第一句话就摆在那边,看了你两个回复,我都觉得你没看懂我也认为控制反转不是模式
引用
和“只和陌生人说话”,“迪米特法则”,“开闭原则”,等作为开发高弹性,高可扩展,高可维护代码的必要法则
一个道理。 说spring的反转控制,spring包含很多框架,我前述讲了,任何框架都是实现了反转控制,否则会退化工具库。回答:这个同意,这就是框架存在的意义,如果什么事都要我们自己干,框架用来做什么呢
|
|
返回顶楼 | |
发表时间:2011-05-31
最后修改:2011-05-31
[quote="kakaluyi"]
[quote="redhat"] [quote="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对象来维护(状态模式) 这两个例子不确切,其实前者你举的这个例子比较明确的是指它实现了封装(隐藏了实现,使用了多态),状态的互相转化没有反战控制,可能你在这些模式里做了些变化实现了控制反转,但是一般我们不认为是。 回答:工厂模式对于实例的创建由父类反转延迟到了子类,状态模式由自己控制状态变化交给了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&q=principle&hl=zh-CN&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对象使用服务对象都算是了。 控制反转强调控制逻辑,而且这些控制逻辑反转,交给非使用/实现的对象。所以你说的回调,观察者模式是控制反转,理解非常到位,目前大家都是公认的。 关于其中有些模式你认为实现了反转控制的,请给出相关出处和引文,好便大家一起探讨,但不管这样,希望都是严谨的,经得起时间考验的。 我这里写的都是大家比较公认的概念,没有创造自己的概念,没有有创造的概念,如果有,会给出确切的含义,以及必要的证明(需要的话,概念不等同于定理。 你讨论的这些都很好,很深入,我觉得此贴应该成为精华帖。 |
|
返回顶楼 | |
发表时间:2011-06-01
最后修改:2011-06-01
状态模式 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(); } } 状态模式一定要有context类来封装变化逻辑, 由context类实现状态的变化,状态模式不是控制反转吗?这个我们的理解出入很大 |
|
返回顶楼 | |
发表时间:2011-06-01
最后修改:2011-06-01
引用 给你举例说明下,Spring的ORM框架,主要是使用了模板方法模式,使我们更好方便的使用,我们只要把处理查询结果回调交给HibernateTemplate类(或者相应的template)即可,至于什么时间调用你的回调,都交给了这些template类,这即是控制的反转。
我怎么觉得这是门面模式呢,不要看到templete就以为用到了模板模式,模板模式比如servlet提供init,dopost,doget,destroy方法,你可以重写,也可不重写。模板方法是搭好框架由我们继承实现,参考listenr,structs的action。 其他真的关于模式真的有很多不同的见解,不过人是活的,模式只是站在别人的经验上看问题,有争论时正常的。特别是控制反转这种抽象的概念,国外大牛之间都有conflict,不要违反基本原则就好 |
|
返回顶楼 | |
发表时间:2011-06-01
kakaluyi 写道
状态模式 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(); } } 状态模式一定要有context类来封装变化逻辑, 由context类实现状态的变化,状态模式不是控制反转吗?这个我们的理解出入很大 bean有setter方法的,但是调用setter的方法逻辑我们是 放在外部程序的,这叫反转控制。context设置状态的变化方法是在context里的,调用控制在外面。这个请你参看/搜索相关文献理解完整的重要。 |
|
返回顶楼 | |
发表时间: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)} } |
|
返回顶楼 | |
发表时间:2011-06-01
最后修改: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对象里),我们应该争论驴子应该拉磨还是应该拖粮食这才有意义。 |
|
返回顶楼 | |