博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入理解IoC(控制反转)、DI(依赖注入)
阅读量:6089 次
发布时间:2019-06-20

本文共 2440 字,大约阅读时间需要 8 分钟。

引述

最近看设计模式以及laravel代码,对于控制反转以及依赖注入这些概念非常困惑,于是找了一些资料,以下是对于控制反转的一下理解。

概念

IoC

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

正如概念中描述的,那么控制反转具体指哪些 控制反转 了呢,其实我理解的控制反转是指程序所控制的对象的控制权交给了容器,而这个容器就是实现各个模块解耦合的关键。IoC只是一种设计思想,主要实现有:

  • 依赖查找(Dependency Lookup):容器提供回调接口和上下文环境给组件。
  • 依赖注入(Dependency Injection)

我们着重说一下依赖注入。

DI

在软件工程中,依赖注入是种实现控制反转用于解决依赖性设计模式。一个依赖关系指的是可被利用的一种对象(即服务提供端) 。依赖注入是将所依赖的传递给将使用的从属对象(即客户端)。该服务是将会变成客户端的状态的一部分。 传递服务给客户端,而非允许客户端来建立或寻找服务,是本设计模式的基本要求。

以上是wikipedia上对于依赖注入的理解,下面将用实际的例子详细讲解。

举例

加入我们设计一个通用的用户登录基类,可以支持多个平台的用户登录

那么最糟糕的写法是,

/** * A类用户登录 **/class User_A_Login{    public function checkALogin(){            };}/** * B类用户登录 **/class User_B_Login{    public function checkBLogin(){            };}/** * 登录基类 **/class User_Login{    public function checkLogin($userType)    {        if($userType = 'A'){            $this->objAUser = new User_A_Login();            $this->objAUser->checkALogin();        }elseif($userType = 'B'){            $this->objBUser = new User_B_Login();            $this->objBUser->checkBLogin();        }    }}

上面的 User_Login 这个类就直接依赖于类 User_A_LoginUser_B_Login ,如果我们使用下面这种方式写

interface User_Login_Interface{    public function checkLogin();}/** * A类用户登录 **/class User_A_Login implements User_Login_Interface{    public function checkLogin(){            };}/** * B类用户登录 **/class User_B_Login implements User_Login_Interface{    public function checkLogin(){            };}/** * 登录基类 **/class User_Login{    public $userLogin;        public function setUser(User_Login_Interface $user){        $this->userLogin = $user;    }        public function checkLogin()    {        $this->userLogin->checkLogin();    }}

如果按照这种方式进行构建代码,我们将依赖项User_B_Login或者User_A_Login通过函数 setUser( ) 注入到类中,调用方式:

$userLogin = new User_Login();$userLogin->setUser(new User_A_Login);$userLogin->checkLogin();

调用方可以控制使用那个登录类型,这就完成了对于不同登录系统的依赖注入。如果你引入了一个新的用户c,只需写一个c的登录类:

/** * C类用户登录 **/class User_C_Login implements User_Login_Interface{    public function checkLogin(){            };}

就可以通过:

$userLogin = new User_Login();$userLogin->setUser(new User_C_Login);$userLogin->checkLogin();

进行登录验证了。在实际代码中由于基类非常复杂需要对登录做一系列处理,所以每次添加登录用户不应该去修改基类。对于一下框架例如laravel的框架是不能修改的,应该就是通过这种方式实现的调用方的自定义。

转载地址:http://pavwa.baihongyu.com/

你可能感兴趣的文章
web.xml中的contextConfigLocation在spring中的作用
查看>>
NYOJ-107 A Famous ICPC Team
查看>>
与众不同 windows phone (44) - 8.0 位置和地图
查看>>
Visual Studio Code 使用 ESLint 增强代码风格检查
查看>>
iOS设备中的推送(二):证书
查看>>
敏捷 - #3 原则:经常提供工作软件 ( #3 Agile - Principle)
查看>>
数据结构与算法:二分查找
查看>>
使用思科模拟器Packet Tracer与GNS3配置IPv6隧道
查看>>
iOS开发-NSPredicate
查看>>
我的友情链接
查看>>
Exchange Server 2003 SP2 数据存储大小限制修改
查看>>
expr命令用法-实例讲解
查看>>
酷派8705救砖
查看>>
iOS10里的通知与推送
查看>>
# C 语言编写二进制/十六进制编辑器
查看>>
EMS SQL Management Studio for MySQL
查看>>
我的友情链接
查看>>
做母亲不容易
查看>>
详细的文档(吐槽)
查看>>
DEVEXPRESS 随记
查看>>