搜索
首页后端开发php教程如何理解IoC(Inversion of Control)?

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

回复内容:

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

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

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

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

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

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

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

Don't call me, I will call you

正常流程

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

于是你回家了。

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

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

第二天,再去看,……

一直到有了这本书。

Ioc

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

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

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

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

你去拿书。


Don't call me, I will call you

IoC就是让框架为我们创建些东西。

<code>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;
});
</code>

据Clouser function特征,上面代的代码不会创建$sms对象。
$app->make('sms')的时候,$sms对象才被创建。所谓的反转大概就是按需创建吧。用的时候才触发创建,不是创建好了等着用。

因为程序员本身是农民工的一种,但是又想装的高大上一些,用以自赏,所以创建了这个很NB的术语,装的好像搞原子弹的。不用太在意。

本质是面向抽象编程,IOC描述的是特性,DI描述的具体实现方式,两者有共通的地方。可以这么理解:用DI实现具备IOC特性的框架,最终体现面向抽象编程的理念,增强系统的可扩性。
常见的“多态”就是面向抽象编程,比如:

<code>Person person = new Male();
person.say();
person.run();
person.eat();
</code>

现在要把person指定为Female,则只需替换第一行即可:

<code>Person person = new Female();
</code>

改动已经很少了,但仍可以做得更彻底一点:可不可以不更改现有代码就完成切换呢?答案就是"DI"。
撇开Spring不谈,咱们自己也完全可以实现一套最简化的类似功能:

<code>Person person = SpringLike.getBeanFromConfig('person');
</code>

这行代码的意思就是,Person的实例是根据配置文件产生的,比如:

<code>person=com.xx.Male
</code>

具体原理不赘述,大家耳熟能详。
回到上面那个问题,现在要把功能切换到Female,则只需更改配置文件即可:

<code>person=com.xx.Female
</code>

将控制权进一步转移到配置文件,因而修改不涉及业务逻辑代码。
可以看出,“DI”是用更彻底的方式使用多态,在面向抽象编程这方面走得更远。"IOC"是面向抽象编程所体现出来的一个特性,本身和“DI”不冲突。

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

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

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

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

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

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

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

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

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

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

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

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

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

IoC,控制反转,把对XX的控制交给别人。
spring的DI就是你把new对象的工作交给spring。

参考Spring Ioc容器
推荐阅读的文章
Inversion of Control Containers and the Dependency Injection pattern
InversionOfControl
自己动手写一个IoC工具

ioc 通俗一点的说,你把他想成一个大工厂,你问他要什么object,他就给你什么object,就是这么简单
他就像一个全局变量,在每个object里面的都可以访问到
你问他要什么object,他就给你什么object

ioc主要作用是用来解析类的实例,为什么要解析?而不是直接获得?因为类有其他类的依赖关系。ioc容器可以把多层级的依赖关系全部解析出来。

如果你看的是Laravel框架,可以看看:Service Container(IOC容器)

依赖注入和控制反转都是为了达到相同的解耦效果,Ioc确实不够开门见山,因此业界称进行了广泛的讨论,最终软件界的泰斗级人物Martin Fowler提出了DI的概念用以替代Ioc,即让调用类对某一接口实现类的依赖关系都第三方(容器或协作类)注入,以移除调用类对某一接口实现类的依赖。

依赖注入是控制反转的一种实现方式。

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
高流量网站的PHP性能调整高流量网站的PHP性能调整May 14, 2025 am 12:13 AM

TheSecretTokeEpingAphp-PowerEdwebSiterUnningSmoothlyShyunderHeavyLoadInVolvOLVOLVOLDEVERSALKEYSTRATICES:1)emplactopCodeCachingWithOpcachingWithOpCacheToreCescriptexecution Time,2)使用atabasequercachingCachingCachingWithRedataBasEndataBaseLeSendataBaseLoad,3)

PHP中的依赖注入:初学者的代码示例PHP中的依赖注入:初学者的代码示例May 14, 2025 am 12:08 AM

你应该关心DependencyInjection(DI),因为它能让你的代码更清晰、更易维护。1)DI通过解耦类,使其更模块化,2)提高了测试的便捷性和代码的灵活性,3)使用DI容器可以管理复杂的依赖关系,但要注意性能影响和循环依赖问题,4)最佳实践是依赖于抽象接口,实现松散耦合。

PHP性能:是否可以优化应用程序?PHP性能:是否可以优化应用程序?May 14, 2025 am 12:04 AM

是的,优化papplicationispossibleandessential.1)empartcachingingcachingusedapcutorediucedsatabaseload.2)优化的atabaseswithexing,高效Quereteries,and ConconnectionPooling.3)EnhanceCodeWithBuilt-unctions,避免使用,避免使用ingglobalalairaiables,并避免使用

PHP性能优化:最终指南PHP性能优化:最终指南May 14, 2025 am 12:02 AM

theKeyStrategiestosiminificallyBoostphpapplicationPermenCeare:1)useOpCodeCachingLikeLikeLikeLikeLikeCacheToreDuceExecutiontime,2)优化AtabaseInteractionswithPreparedStateTemtStatementStatementSandProperIndexing,3)配置

PHP依赖注入容器:快速启动PHP依赖注入容器:快速启动May 13, 2025 am 12:11 AM

aphpdepentioncontiveContainerIsatoolThatManagesClassDeptions,增强codemodocultion,可验证性和Maintainability.itactsasaceCentralHubForeatingingIndections,因此reducingTightCightTightCoupOulplingIndeSingantInting。

PHP中的依赖注入与服务定位器PHP中的依赖注入与服务定位器May 13, 2025 am 12:10 AM

选择DependencyInjection(DI)用于大型应用,ServiceLocator适合小型项目或原型。1)DI通过构造函数注入依赖,提高代码的测试性和模块化。2)ServiceLocator通过中心注册获取服务,方便但可能导致代码耦合度增加。

PHP性能优化策略。PHP性能优化策略。May 13, 2025 am 12:06 AM

phpapplicationscanbeoptimizedForsPeedAndeffificeby:1)启用cacheInphp.ini,2)使用preparedStatatementSwithPdoforDatabasequesies,3)3)替换loopswitharray_filtaray_filteraray_maparray_mapfordataprocrocessing,4)conformentnginxasaseproxy,5)

PHP电子邮件验证:确保正确发送电子邮件PHP电子邮件验证:确保正确发送电子邮件May 13, 2025 am 12:06 AM

phpemailvalidation invoLvesthreesteps:1)格式化进行regulareXpressecthemailFormat; 2)dnsvalidationtoshethedomainhasavalidmxrecord; 3)

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。