Laravel中的控制反转+依赖注入+依赖反转+反射+容器+服务提供者+门面

1、控制反转(IoC): 不需要自己内容修改,改成由外部传递。从依赖内部改为依赖外部
2、依赖注入(DI):不是由自己内部new对象或者实例,而是通过构造函数或方法传入调用其他类的都属于依赖注入 。

                   原始代码

           

                      控制反转和依赖注入

左边的问题:假设现在想用数据库记录日志的话,我们就得修改User类,这份代码没达到解耦合,也不符合编程开放封闭原则。
解决:右边的控制反转和依赖注入。其中,$user = new User(new DatabaseLog());是Contracts契约(面向接口编程) 

控制反转(IOC)、依赖注入(DI)、依赖反转(DIP)的三者的区别联系?

1、控制反转(IOC):Inversion Of Control,'控制'是对程序执行流程的控制,'反转'是没使用框架前,程序员自己控制整个程序执行,使用框架后,控制权从程序员反转到了框架。

2、依赖注入(DI):Dependency Injection,与IOC相反,一种具体的编码技巧,可简记为:
不通过new()方式在类内部创建依赖类对象,而是将依赖类对象在外部创建好,通过构造函数或函数参数等注入给类使用。即:一个组件内部依赖一个对象,但他不自己造,等别人送上来
---依赖注入框架:通过依赖注入框架提供的扩展点,简单配置下所有需要的类及类与类之间依赖关系,就可实现由框架来自动创建对象,管理对象的生命周期、依赖注入等原本需要程序员来做的事情。

3、依赖反转(DIP)原则:Dependency Inversion,高层模块不要依赖低层模块(调用者属于高层,被调用者属于低层),之间应该通过抽象来相互依赖。抽象不该依赖实现细节,实现细节依赖抽象。

综合:控制反转是编程思想,把控制权交给第三方;依赖注入是实现控制反转最典型的方法,底层实现要符合“里氏替换”原则,子类的可替换,使得父类模块依赖于抽象的高层模块,实现程序的可扩展性。
依赖注入采用“基于接口而非实现编程”,即:一个组件内部依赖一个对象,但他不自己造,等别人送上来。

基于接口而非实现编程 与 依赖注入 的联系与区别?

联系:都是从外部传入依赖对象,而不是在内部new一个出来
区别:前者强调接口,强调依赖的对象是接口,而不是具体的实现类;后者是类和接口都可以,只要是从外部传入,而不是内部new出来的。


3、反射:

$reflector = new reflectionClass(User::class);//获取User的reflectionClass对象
$constructor = $reflector->getConstructor();//拿到User的构造函数
$dependencies = $constructor->getParameters();//拿到User的构造函数的所有依赖参数
$user = $reflector->newInstance();//创建user对象
$user = $reflector->newInstanceArgs($dependencies = []);//创建user对象,需要传递参数的

反射的使用:类的实例化由make来创建

4、容器:把各种类的创建放在一个闭包中,闭包的好处是使用时再创建(懒加载的思想)。包含两部分:bind + make
使用容器的好处:假如我们项目里有很多功能用到了这个login功能,我们则在这几个页面反复写。突然我们有一天换需求了,觉得数据库记录日志不太好,想要改成文件的,那我们不是每个页面用到login功能的都去替换成new FileLog()呢?,那如何修改呢?

相关文档详见:控制反转+依赖注入+反射   容器+服务提供者
相关源码详见:反射   容器

5、服务提供者(ServiceProvider):服务提供者是食物,容器是篮子,服务提供者注册到容器,相当于把各种食物放进篮子里。
使用场景:可以借助一个容器,提前把 log,user 都绑定到 Ioc 容器中。User 的创建交给这个容器去做。比如下面这样的,你再任何地方使用 login。都不需要关心是用什么记录日志了,哪怕后期需要修改只需要在 ioc 容器修改绑定其他记录方式日志就行了。

         入口处的服务提供者(Http\Kernel)

                             其它服务提供者(Http\Kernel)

6、外观模式/门面(Facades):Facade核心实现原理就是在 UserFacade 提前注入 Ioc 容器
使用场景:需要$ioc->make('user')才能拿到User的实例,再去使用$user->login();那能不能更方便点,用这种方式:UserFacade::login(); 
步骤:
(1)定义一个服务提供者的外观类,在该类定义一个类的变量,跟 ioc 容器绑定的 key 一样;
(2)通过静态魔术方法__callStatic 可以得到当前想要调用的 login;
(3)使用 static::$ioc->make('user');

从代码看,使用Facade更加麻烦了,还需要注入ioc容器,还得需要用魔术方法。其实laravel在框架运行的时候这些步骤都帮我们自动加好了,我们只需要使用UserFacade::login ();就可以了。使用 Facades 其实最主要的就是它提供了(1)简单,易记的语法,从而无需手动注入或配置长长的类名。此外,由于他们对PHP静态方法的独特调用,使得(2)测试起来非常容易

猜你喜欢

转载自blog.csdn.net/wuhuagu_wuhuaguo/article/details/105639076