依赖注入

laravel依赖注入是A类在依赖B类时,可以直接在容器中直接注入B类和A类,容器会自己去寻找依赖,而不用担心A类和B类谁先注入到容器。

新建立两个文件(注意这两个文件的namespace),一个是:

  1. <?php
  2. namespace App\Http\Controllers\User;
  3. class People
  4. {
  5. public $dog = null;
  6. /**
  7. * People constructor.
  8. * @param \App\Http\Controllers\User\Dog $dog
  9. */
  10. public function __construct(Dog $dog)
  11. {
  12. $this->dog = $dog;
  13. }
  14. public function putDog(){
  15. return $this->dog->dogCall();
  16. }
  17. }

另一个是:

  1. <?php
  2. namespace App\Http\Controllers\User;
  3. class Dog
  4. {
  5. public function dogCall(){
  6. return '汪汪汪';
  7. }
  8. }

在route中建立一条路由:

  1. Route::get('user/test', 'User\UserController@test');

最后建立一个contorller

  1. <?php
  2. namespace App\Http\Controllers\User;
  3. use Illuminate\Foundation\Bus\DispatchesJobs;
  4. use Illuminate\Routing\Controller as BaseController;
  5. use Illuminate\Foundation\Validation\ValidatesRequests;
  6. use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
  7. use Illuminate\Contracts\Container\Container;
  8. class UserController extends BaseController
  9. {
  10. use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
  11. public function test(Container $container)
  12. {
  13. /*People类和Dog类也可以在config/App.php中注入,就不用在这里注入了
  14. 'aliases' => [
  15. 'Dog' => App\Http\Controllers\User\Dog::class,
  16. 'People' => App\Http\Controllers\User\People::class,
  17. ]
  18. */
  19. $container->bind('People', 'App\Http\Controllers\User\People'); //注入People这个类,People这个类依赖于Dog这个类,但是People也可以先注入,不会报错
  20. $container->bind('Dog', 'App\Http\Controllers\Dog'); //注入Dog这个类,
  21. $people = $container->make('People'); //想要用到People类,直接去取就可以了,不会关心People类在哪里
  22. echo $people->putDog();
  23. }
  24. }

这个就是人依赖狗,只要在容器(Container)里把狗这个类注入就行了。

接下来要聊下是:
Laravel 通过服务容器来管理类依赖并进行依赖注入。如果使用一个接口作为函数参数的类型提示,这个时候就需要将指定的实现绑定到接口上面。现在我们要把dog给抽象出来一个Animal。
如下:

  1. <?php
  2. namespace App\Http\Controllers\User;
  3. interface Animal
  4. {
  5. public function dogCall();
  6. }

然后把注入改一下:

  1. $container->bind('App\Http\Controllers\User\Animal', 'App\Http\Controllers\User\Dog'); //注意和以前的那个注入相比,现在我们是把实现绑定到接口上面

这个就是所谓的面向接口编程,接口可以理解为一个规范、一个约束。高层模块不直接依赖于低层模块,它们都应该依赖于抽象(指接口)。

使用依赖注入,最重要的一点好处就是有效的分离了对象和它所需要的外部资源,使得它们松散耦合,有利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

控制反转

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

  1. <?php
  2. /**
  3. * 没有IoC/DI的时候,常规的A类使用C类的示例
  4. */
  5. /**
  6. * Class c
  7. */
  8. class c
  9. {
  10. public function say()
  11. {
  12. echo 'hello';
  13. }
  14. }
  15. /**
  16. * Class a
  17. */
  18. class a
  19. {
  20. private $c;
  21. public function __construct()
  22. {
  23. $this->c = new C(); // 实例化创建C类
  24. }
  25. public function sayC()
  26. {
  27. echo $this->c->say(); // 调用C类中的方法
  28. }
  29. }
  30. $a = new a();
  31. $a->sayC();

当有了IoC/DI的容器后,A类不再主动去创建C了,如下图所示:


而是被动等待,等待IoC/DI的容器获取一个C的实例,然后反向的注入到A类中,如下图所示:

  1. <?php
  2. /**
  3. * 当有了IoC/DI的容器后,a类依赖c实例注入的示例
  4. */
  5. /**
  6. * Class c
  7. */
  8. class c
  9. {
  10. public function say()
  11. {
  12. echo 'hello';
  13. }
  14. }
  15. /**
  16. * Class a
  17. */
  18. class a
  19. {
  20. private $c;
  21. public function setC(C $c)
  22. {
  23. $this->c = $c; // 实例化创建C类
  24. }
  25. public function sayC()
  26. {
  27. echo $this->c->say(); // 调用C类中的方法
  28. }
  29. }
  30. $c = new C();
  31. $a = new a();
  32. $a->setC($c);
  33. $a->sayC();

参考:https://segmentfault.com/a/1190000007536704

分类: web

标签:   laravel