search

Home  >  Q&A  >  body text

php - 如何理解IoC(Inversion of Control)?

RT,如何理解IoC(Inversion of Control)?如果能写个demo解释最好了。

伊谢尔伦伊谢尔伦2820 days ago1017

reply all(17)I'll reply

  • 伊谢尔伦

    伊谢尔伦2017-04-10 15:13:10

    我试着搜了一下,中文资料基本都把IoC(控制翻转)和DI(依赖注入)混为一谈,就连StackOverflow上的第一位答案也犯了同样的问题(幸好下面有高票的反对评论,否则我的世界观都快坏掉了)

    控制翻转是代码复用的一种模式(注意不是设计模式)

    一般(非IoC)的复用,通常是用户代码调用组件(任意形式的被复用的代码,本答案中统称为组件)。也就是用户代码解决“Why it works, What to do”,组件解决“How to do”,逻辑的入口是用户代码,

    而控制翻转则是组件来调用用户代码,也就是组件解决“Why it works, When to do”,用户代码解决“What to do”,逻辑的入口是组件

    下面是除了DI之外的控制翻转的例子

    • 接口/虚函数 组件调用接口/虚函数,具体由用户代码实现
    • 发布订阅(事件)模式 组件触发事件,用户代码订阅事件
    • 回调 用户代码写回调,组件来调用
    • 几乎所有能被称之为框架的东西 用户代码在规定的地方实现具体业务逻辑,剩下的框架负责

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 15:13:10

    通俗的说,一个项目由各个类组成。一个类在一个项目会被很多地方使用。

    如果按照传统的写法就是每个用的地方都需要 new Class()
    如果参数很复杂,每个地方都需要new Class(param1, param2, param3, ..)
    此时每次修改类的构造函数, 那么每个地方需要跟着修改。工作量大,耦合度高。

    但是可以把需要使用的类,初始化一次,放到一个容器中保存起来,其他需要使用的地方,
    只需要调用容器的方法Container->getClassINeed()
    那么,使用这个类和生成这个类通过中间的容器分开了。
    示例可以看Phalcon框架,文档里给的例子,教你一步步搭建自己的容器

    一些管理对象生成的设计模式,本身也算一种容器的实现, 例如常见的工厂模式

    reply
    0
  • 黄舟

    黄舟2017-04-10 15:13:10

    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的术语,装的好像搞*的。不用太在意。

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-10 15:13:10

    Don't call me, I will call you

    正常流程

    你去图书馆借书,但是没有。

    于是你回家了。

    然后你每个天去一趟图书馆,看你的书到了没有。

    如果还没有,那么你回家,继续等……

    第二天,再去看,……

    一直到有了这本书。

    Ioc

    你去图书馆借书,但是没有。

    于是你登记了一下,就回家了。

    回到家,刷刷微博,刷刷sf,撸撸代码。

    等书到了,管理员通知你。

    你去拿书。


    Don't call me, I will call you

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 15:13:10

    本质是面向抽象编程,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”不冲突。

    reply
    0
  • 阿神

    阿神2017-04-10 15:13:10

    举个例子,有一天,你去庆丰包子铺吃包子,进门后你首先需要找到点餐台在哪,然后告诉服务员你要什么,然后去领餐口领包子。这是以你为主的流程,一切都在你的掌握之下,但如果你不主动,就没有包子吃。

    第二天,你去另一家高大上包子铺吃包子,这里,你只要坐下来说一句我要吃包子,就有服务员给你把包子端上来。这是以餐厅为主的流程,你不需要知道去哪点餐,去哪领包子。

    如果把第一个流程作为“正”的话,那第二个流程就是“反”过来了。这就是所谓的IoC。不过,这个名字起的不太容易理解,因为正、反的概念是相对的,你也可以说第二个流程是正的。

    把这个概念应用到GUI编程上,就是顺序执行和事件处理的区别。本来是你自己写的程序按顺序执行,例如第一步输入用户名,第二部输入密码,然后执行登录操作。使用了Windows或者其他图形界面框架后,就是由框架来负责运行你的程序,并且在用户输入了内容之后通知你的程序,你再去做处理。相对于顺序执行,事件驱动就是IoC的一种表现形式。

    把这个概念应用到依赖管理上,假设你的程序需要引用另一个对象,本来你是需要在代码里创建这个对象,应用IoC模式后,你的程序不再去主动创建第三方对象,而是运行在一个容器或者框架里,例如Spring,然后等着Spring把你需要的对象创建好传递进来。这就是依赖注入(DI),IoC的另一种表现形式。

    reply
    0
  • 黄舟

    黄舟2017-04-10 15:13:10

    由于三言两语说不清楚,我写了一篇文章在这里,http://segmentfault.com/blog/zhaoyi/1190000002411255

    reply
    0
  • 迷茫

    迷茫2017-04-10 15:13:10

    建议看看spring框架的原理,就是依赖注册

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-10 15:13:10

    正常的写法,都是上层调用底层封装好的方法,由底层提供接口,所谓的控制反转指的是,底层的执行逻辑可以由上层来决定,写的是什么,底层就执行什么,它的好处在于灵活、易扩展,就像@bigxu 写的代码一样。

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 15:13:10

    顧名思義吧,你寫出的程式是在操縱些什麼,比如說,給一些數據搬家,但是怎麼來指揮你的程式開始操控它要操控的對象呢?那麼你有要寫一些程式來做指(調)揮(用)你的程式,你定義一個規則,或者遵循一套規則,以便讓人來操控自身,其實這就是控制反轉,即,你是要把控制權交給別人的,仔細想想,其實這種反轉無處不在,更重要的是,怎麼讓別人來調用你的程式?需要約定接口,所以IoC也引導你更多的從面向接口方面考慮編程問題

    reply
    0
  • Cancelreply