RT,如何理解IoC(Inversion of Control)?如果能写个demo解释最好了。
小伙看你根骨奇佳,潜力无限,来学PHP伐。
我试着搜了一下,中文资料基本都把IoC(控制翻转)和DI(依赖注入)混为一谈,就连StackOverflow上的第一位答案也犯了同样的问题(幸好下面有高票的反对评论,否则我的世界观都快坏掉了)
控制翻转是代码复用的一种模式(注意不是设计模式)
一般(非IoC)的复用,通常是用户代码调用组件(任意形式的被复用的代码,本答案中统称为组件)。也就是用户代码解决“Why it works, What to do”,组件解决“How to do”,逻辑的入口是用户代码,
而控制翻转则是组件来调用用户代码,也就是组件解决“Why it works, When to do”,用户代码解决“What to do”,逻辑的入口是组件
下面是除了DI之外的控制翻转的例子
通俗的说,一个项目由各个类组成。一个类在一个项目会被很多地方使用。
如果按照传统的写法就是每个用的地方都需要 new Class() 如果参数很复杂,每个地方都需要new Class(param1, param2, param3, ..) 此时每次修改类的构造函数, 那么每个地方需要跟着修改。工作量大,耦合度高。
new Class()
new Class(param1, param2, param3, ..)
但是可以把需要使用的类,初始化一次,放到一个容器中保存起来,其他需要使用的地方, 只需要调用容器的方法Container->getClassINeed() 那么,使用这个类和生成这个类通过中间的容器分开了。 示例可以看Phalcon框架,文档里给的例子,教你一步步搭建自己的容器
Container->getClassINeed()
Phalcon
一些管理对象生成的设计模式,本身也算一种容器的实现, 例如常见的工厂模式
IoC就是让框架为我们创建些东西。
App::bind('sms', function () { // Create a new SMS component. $sms = new SMSClient; $sms->setUsername('shauna'); $sms->setPassword('1_5t341_c4t5!'); // Return the created SMS component. return $sms; });
据Clouser function特征,上面代的代码不会创建$sms对象。 $app->make('sms')的时候,$sms对象才被创建。所谓的反转大概就是按需创建吧。用的时候才触发创建,不是创建好了等着用。
因为程序员本身是农民工的一种,但是又想装的高大上一些,用以自赏,所以创建了这个很NB的术语,装的好像搞*的。不用太在意。
Don't call me, I will call you
你去图书馆借书,但是没有。
于是你回家了。
然后你每个天去一趟图书馆,看你的书到了没有。
如果还没有,那么你回家,继续等……
第二天,再去看,……
一直到有了这本书。
于是你登记了一下,就回家了。
回到家,刷刷微博,刷刷sf,撸撸代码。
等书到了,管理员通知你。
你去拿书。
本质是面向抽象编程,IOC描述的是特性,DI描述的具体实现方式,两者有共通的地方。可以这么理解:用DI实现具备IOC特性的框架,最终体现面向抽象编程的理念,增强系统的可扩性。 常见的“多态”就是面向抽象编程,比如:
Person person = new Male(); person.say(); person.run(); person.eat();
现在要把person指定为Female,则只需替换第一行即可:
Person person = new Female();
改动已经很少了,但仍可以做得更彻底一点:可不可以不更改现有代码就完成切换呢?答案就是"DI"。 撇开Spring不谈,咱们自己也完全可以实现一套最简化的类似功能:
Person person = SpringLike.getBeanFromConfig('person');
这行代码的意思就是,Person的实例是根据配置文件产生的,比如:
person=com.xx.Male
具体原理不赘述,大家耳熟能详。 回到上面那个问题,现在要把功能切换到Female,则只需更改配置文件即可:
person=com.xx.Female
将控制权进一步转移到配置文件,因而修改不涉及业务逻辑代码。 可以看出,“DI”是用更彻底的方式使用多态,在面向抽象编程这方面走得更远。"IOC"是面向抽象编程所体现出来的一个特性,本身和“DI”不冲突。
举个例子,有一天,你去庆丰包子铺吃包子,进门后你首先需要找到点餐台在哪,然后告诉服务员你要什么,然后去领餐口领包子。这是以你为主的流程,一切都在你的掌握之下,但如果你不主动,就没有包子吃。
第二天,你去另一家高大上包子铺吃包子,这里,你只要坐下来说一句我要吃包子,就有服务员给你把包子端上来。这是以餐厅为主的流程,你不需要知道去哪点餐,去哪领包子。
如果把第一个流程作为“正”的话,那第二个流程就是“反”过来了。这就是所谓的IoC。不过,这个名字起的不太容易理解,因为正、反的概念是相对的,你也可以说第二个流程是正的。
把这个概念应用到GUI编程上,就是顺序执行和事件处理的区别。本来是你自己写的程序按顺序执行,例如第一步输入用户名,第二部输入密码,然后执行登录操作。使用了Windows或者其他图形界面框架后,就是由框架来负责运行你的程序,并且在用户输入了内容之后通知你的程序,你再去做处理。相对于顺序执行,事件驱动就是IoC的一种表现形式。
把这个概念应用到依赖管理上,假设你的程序需要引用另一个对象,本来你是需要在代码里创建这个对象,应用IoC模式后,你的程序不再去主动创建第三方对象,而是运行在一个容器或者框架里,例如Spring,然后等着Spring把你需要的对象创建好传递进来。这就是依赖注入(DI),IoC的另一种表现形式。
由于三言两语说不清楚,我写了一篇文章在这里,http://segmentfault.com/blog/zhaoyi/1190000002411255
建议看看spring框架的原理,就是依赖注册
正常的写法,都是上层调用底层封装好的方法,由底层提供接口,所谓的控制反转指的是,底层的执行逻辑可以由上层来决定,写的是什么,底层就执行什么,它的好处在于灵活、易扩展,就像@bigxu 写的代码一样。
顧名思義吧,你寫出的程式是在操縱些什麼,比如說,給一些數據搬家,但是怎麼來指揮你的程式開始操控它要操控的對象呢?那麼你有要寫一些程式來做指(調)揮(用)你的程式,你定義一個規則,或者遵循一套規則,以便讓人來操控自身,其實這就是控制反轉,即,你是要把控制權交給別人的,仔細想想,其實這種反轉無處不在,更重要的是,怎麼讓別人來調用你的程式?需要約定接口,所以IoC也引導你更多的從面向接口方面考慮編程問題
我试着搜了一下,中文资料基本都把IoC(控制翻转)和DI(依赖注入)混为一谈,就连StackOverflow上的第一位答案也犯了同样的问题(幸好下面有高票的反对评论,否则我的世界观都快坏掉了)
控制翻转是代码复用的一种模式(注意不是设计模式)
一般(非IoC)的复用,通常是用户代码调用组件(任意形式的被复用的代码,本答案中统称为组件)。也就是用户代码解决“Why it works, What to do”,组件解决“How to do”,逻辑的入口是用户代码,
而控制翻转则是组件来调用用户代码,也就是组件解决“Why it works, When to do”,用户代码解决“What to do”,逻辑的入口是组件
下面是除了DI之外的控制翻转的例子
通俗的说,一个项目由各个类组成。一个类在一个项目会被很多地方使用。
但是可以把需要使用的类,初始化一次,放到一个容器中保存起来,其他需要使用的地方,
只需要调用容器的方法
Container->getClassINeed()
那么,使用这个类和生成这个类通过中间的容器分开了。
示例可以看
Phalcon
框架,文档里给的例子,教你一步步搭建自己的容器一些管理对象生成的设计模式,本身也算一种容器的实现, 例如常见的工厂模式
IoC就是让框架为我们创建些东西。
据Clouser function特征,上面代的代码不会创建$sms对象。
$app->make('sms')的时候,$sms对象才被创建。所谓的反转大概就是按需创建吧。用的时候才触发创建,不是创建好了等着用。
因为程序员本身是农民工的一种,但是又想装的高大上一些,用以自赏,所以创建了这个很NB的术语,装的好像搞*的。不用太在意。
正常流程
你去图书馆借书,但是没有。
于是你回家了。
然后你每个天去一趟图书馆,看你的书到了没有。
如果还没有,那么你回家,继续等……
第二天,再去看,……
一直到有了这本书。
Ioc
你去图书馆借书,但是没有。
于是你登记了一下,就回家了。
回到家,刷刷微博,刷刷sf,撸撸代码。
等书到了,管理员通知你。
你去拿书。
本质是面向抽象编程,IOC描述的是特性,DI描述的具体实现方式,两者有共通的地方。可以这么理解:用DI实现具备IOC特性的框架,最终体现面向抽象编程的理念,增强系统的可扩性。
常见的“多态”就是面向抽象编程,比如:
现在要把person指定为Female,则只需替换第一行即可:
改动已经很少了,但仍可以做得更彻底一点:可不可以不更改现有代码就完成切换呢?答案就是"DI"。
撇开Spring不谈,咱们自己也完全可以实现一套最简化的类似功能:
这行代码的意思就是,Person的实例是根据配置文件产生的,比如:
具体原理不赘述,大家耳熟能详。
回到上面那个问题,现在要把功能切换到Female,则只需更改配置文件即可:
将控制权进一步转移到配置文件,因而修改不涉及业务逻辑代码。
可以看出,“DI”是用更彻底的方式使用多态,在面向抽象编程这方面走得更远。"IOC"是面向抽象编程所体现出来的一个特性,本身和“DI”不冲突。
举个例子,有一天,你去庆丰包子铺吃包子,进门后你首先需要找到点餐台在哪,然后告诉服务员你要什么,然后去领餐口领包子。这是以你为主的流程,一切都在你的掌握之下,但如果你不主动,就没有包子吃。
第二天,你去另一家高大上包子铺吃包子,这里,你只要坐下来说一句我要吃包子,就有服务员给你把包子端上来。这是以餐厅为主的流程,你不需要知道去哪点餐,去哪领包子。
如果把第一个流程作为“正”的话,那第二个流程就是“反”过来了。这就是所谓的IoC。不过,这个名字起的不太容易理解,因为正、反的概念是相对的,你也可以说第二个流程是正的。
把这个概念应用到GUI编程上,就是顺序执行和事件处理的区别。本来是你自己写的程序按顺序执行,例如第一步输入用户名,第二部输入密码,然后执行登录操作。使用了Windows或者其他图形界面框架后,就是由框架来负责运行你的程序,并且在用户输入了内容之后通知你的程序,你再去做处理。相对于顺序执行,事件驱动就是IoC的一种表现形式。
把这个概念应用到依赖管理上,假设你的程序需要引用另一个对象,本来你是需要在代码里创建这个对象,应用IoC模式后,你的程序不再去主动创建第三方对象,而是运行在一个容器或者框架里,例如Spring,然后等着Spring把你需要的对象创建好传递进来。这就是依赖注入(DI),IoC的另一种表现形式。
由于三言两语说不清楚,我写了一篇文章在这里,http://segmentfault.com/blog/zhaoyi/1190000002411255
建议看看spring框架的原理,就是依赖注册
正常的写法,都是上层调用底层封装好的方法,由底层提供接口,所谓的控制反转指的是,底层的执行逻辑可以由上层来决定,写的是什么,底层就执行什么,它的好处在于灵活、易扩展,就像@bigxu 写的代码一样。
顧名思義吧,你寫出的程式是在操縱些什麼,比如說,給一些數據搬家,但是怎麼來指揮你的程式開始操控它要操控的對象呢?那麼你有要寫一些程式來做指(調)揮(用)你的程式,你定義一個規則,或者遵循一套規則,以便讓人來操控自身,其實這就是控制反轉,即,你是要把控制權交給別人的,仔細想想,其實這種反轉無處不在,更重要的是,怎麼讓別人來調用你的程式?需要約定接口,所以IoC也引導你更多的從面向接口方面考慮編程問題