PHP依赖注入容器知识点浅析
依赖注入容器理解
耦合
一个好的代码结构设计一定是松耦合的,这也是很多通用设计模式的宗旨,就是把分散在各处的同一个功能的代码汇聚到一起,形成一个模块,然后在不同模块之间通过一些细小的、明确的渠道进行沟通。
在实践中,不同功能和模块之间的互相依赖是不可避免的,而如何处理好这些依赖之间的关系则是代码结构能否变得美好的关键。
<?php
class User
{
public function register($user)
{
// 注册操作
...
// 发送确认邮件
$notify = new Notify();
$notify- sendEmail('register', $user);
}
}
class Notify
{
public function sendEmail($type, $data)
{
switch $type {
case 'register':
// 发送注册确认邮件
$email = new Email($type);
$email- send($data);
...
}
}
}
class Email
{
public function send($data)
{
// 发送邮件
}
}
上述代码中,三个类之间逐层依赖,三个类实例化的顺序是 User – Notify – Email
也就是说我先实例化User类,可能执行了一些代码之后再去实例化我需要的其他类,比如Notify,以此类推。
这种依赖会让我们不得不为了得到需要的依赖而去做的一些准备工作,有时候可能一个new操作还不够。而这部分工作就是所说的耦合,他会让一个独立功能的类不得不去关心一些和自己的主体功能没什么关系的操作。
解除一个类对其他类的依赖
要解决这个问题也很简单,我可以先实例化好Email类,然后再实例化Notify,然后把Email对象作为参数传给Notify,最后实例化User类,然后把Notify传进去。这就是所谓的依赖注入,可以看到这个过程中类实例化的顺序完全反过来了,先实例化被依赖的对象,而不是先实例化最终需要的对象,这是控制反转。
代码如下:
<?php
$email = new Email();
$notify = new Notify($email);
$user = new User($notify);
可以通过构造函数来注入需要的依赖,也可以用一些其他的方法。
用容器托管依赖
那又有新的问题,例子中只有三个类还好,那如果这个User类依赖Notify来发邮件,依赖Model来存数据库,依赖redis来缓存,这样固然把依赖关系转移到了类的外部,但还是会导致我只想实例化一下User的时候,却要手动做很多的准备工作,会让代码混乱。所以这个时候需要一个容器。而这个容器的作用就是替我来管理这些依赖。
<?php
// 容器
class Container implements ArrayAccess
{
protected $values = [];
public function offsetGet($offset)
{
return $this- values[$offset]($this);
}
public function offsetSet($offset, $value)
{
$this- values[$offset] = $value;
}
}
在程序启动的时候,我们可以在一个地方统一的注册好一系列的基础服务。
<?php
$container = new Container();
$container['notify'] = function($c) {
return new Notify();
};
$container['email'] = function($c) {
return new Email();
};
就会变成这样
<?php
class User
{
public function register($user)
{
// 注册操作
...
// 发送确认邮件
$container('notify')- sendEmail('register', $user);
}
}
class Notify
{
public function sendEmail($type, $data)
{
switch $type {
case 'register':
// 发送注册确认邮件
$email = $container['email'];
$email- send($data);
...
}
}
}
class Email
{
public function send($data)
{
// 发送邮件
}
}
就是当User需要Notify的时候,会去向容器要这个类的对象,那至于Notify再依赖什么其他的东西,我就不用管了,因为Notify也会去向容器要它自己需要的依赖。所有这些依赖关系的处理就完全托管给容器了,我们既不需要去关心依赖之间的层次关系,也避免了依赖之间的耦合。
需要注意的是,依赖注入容器一般只接受一个匿名函数,而不是一个实例化好的对象,匿名函数会告诉容器怎样去获得一个对象,这样可以使得一个服务在被需要的时候才会去实例化
以上就是本次介绍的全部相关知识点,感谢大家的学习和对ZaLou.Cn的支持。
- php概述
- php教程
- php环境搭建
- PHP书写格式
- php变量
- php常量
- PHP注释
- php数组
- php字符串 string
- PHP整型 integer
- PHP浮点型 float
- php布尔型
- php数据类型之数组
- php数据类型之对象
- php数据类型之null
- php数据类型之间的转换
- php运算符
- php表达式
- PHP循环控制
- PHP流程控制
- php函数
- php全局变量
- PHP魔术变量
- php命名空间
- php 日期
- PHP包含文件
- php文件
- PHP 文件上传
- php Cookies
- php Sessions
- php email
- php安全email
- php错误处理
- PHP异常处理
- php过滤器
- PHP 高级过滤器
- php json
- php 表单
- PHP MySQL 简介
- PHP 连接 MySQL
- php创建数据库
- php 创建表
- php mysq 插入数据
- PHP MySQL 插入多条数据
- PHP MySQL 预处理语句
- php mysql 读取数据
- php mysql where
- PHP MySQL Order By
- PHP MySQL Update
- PHP MySQL Delete
- php ODBC
- PHP读取文件,解决中文乱码UTF-8的方法分析
- Linux低电量自动关机的实现办法
- php设计模式之工厂方法模式分析【星际争霸游戏案例】
- PHP+Apache实现二级域名之间共享cookie的方法
- linux虚拟机配置静态IP地址的完整步骤
- laravel-admin利用ModelTree实现对分类信息的管理
- Linux系统下快速配置HugePages的完整步骤
- Laravel5.1 框架关联模型之后操作实例分析
- PHP实现的多进程控制demo示例
- 你可能不知道的一些linux文件权限管理办法
- Laravel框架路由与MVC实例详解
- python实现学生管理系统开发
- 使用 chkconfig 和 systemctl 命令启用或禁用 Linux 服务的办法
- PHP defined()函数的使用图文详解
- 详解在Linux中清空或删除大文件内容的5种办法