PHP 控制反转(IOC)和依赖注入(DI)

对于 “控制反转(IOC)” 和 “依赖注入(DI)” 两个概念,首先要明白以下概念:

  • 控制反转(IOC)是一种思想,依赖注入(DI)是实施这种思想的方法;
  • IOC 意味着将你设计好的对象交给容器控制,而不是传统的在对象内部控制;
  • 依赖注入(DI)实现了控制反转(IOC);

依赖注入的实现#

一:接口注入#

<?php

/**
 * 定义一个消息接口
 * Interface Message
 */
interface Message
{
    public function send();
}

/**
 * 发送邮件的消息类
 * Class SendEmail
 */
class SendEmail implements Message
{

    public function send()
    {
        echo "email 发送成功!";
    }
}

/**
 * 发送短信的消息类
 * Class SendSms
 */
class SendSms implements Message
{

    public function send()
    {
        echo "sms 发送成功!";
    }
}

/**
 * 模拟购买流程
 * Class Order
 */
class Order
{
    //TODO::下单
    //TODO::购买
    //发送消息

    /**
     * @var String 消息内容
     */
    protected String $message;

    function __construct(Message $message)
    {
        $this->message = $message;
    }

    public function send_msg()
    {
        return $this->message->send();
    }
}

//TODO::比如购买成功了,这里开始发送消息
$message = new SendEmail();//发送邮件
//$message = new SendEmail();//发送短信
$order = new Order($message);
$order->send_msg();

分析#

Order 类依赖消息类的 Message 接口

$order = new Order($message);

具体的消息类实例化交给外部处理,不论你是发送短信还是邮件,你自己实例化就好,不要影响我的 Order 类,你只需要把 Message 的接口实现类给我就好

$message = new SendEmail();//发送邮件
//$message = new SendEmail();//发送短信
$order = new Order($message); 
$order->send_msg();

二:构造器注入#

<?php

/**
 * 构造器注入
 * 定义一个有构造函数的类
 * Class IocB
 */
class iocAA
{
    public $b;

    public $c;

    public function __construct($iocB, $iocC)
    {
        $this->b = $iocB;
        $this->c = $iocC;
    }

    public function Method()
    {
        $this->b->Method();
        $this->c->Method();
    }
}

class IocB
{

    public function Method()
    {
        echo '我是 IocB 的 Method 方法';
    }
}

class IocC
{
    public function Method()
    {
        echo '我是 IocC 的 Method 方法';
    }
}
$a = new iocAA(new IocB(), new IocC());
$a->Method();

分析#

进行实例化类的时候,对构造函数的两个参数进行实例化赋值(将实例化后的对象赋值给 iocAA 类 的两个属性)

$a = new iocAA(new IocB(), new IocC());

然后调用对象的方法即可

$a->Method();

三:setter 方法注入#

<?php

class IocC
{
    private $db;

    private $file;

    function setDb($db)
    {
        $this->db = $db;
    }

    function setFile($file)
    {
        $this->file = $file;
    }
}

class file
{
    public function __construct()
    {
        echo "file 的 构造函数执行了" . "\n";
    }

    public function run()
    {
        echo "file 的 run" . "\n";
    }
}

class db
{
    public function __construct()
    {
        echo "db 的 构造函数执行了" . "\n";
    }

    public function run()
    {
        echo "db 的 run" . "\n";
    }
}

$iocC = new IocC();
$iocC->setdb(new db());
$iocC->setfile(new file());

分析#

先实例化 IocC 类

$iocC = new IocC();

接着调用 IocC 类的方法使用,调用 IocC 的方法 setDb 和 setFile 的时候,需要把实例化的对象当做参数传进去

$iocC->setdb(new db());
$iocC->setfile(new file());
本作品采用《CC 协议》,转载必须注明作者和本文链接
✍️博客文章皆为网络收藏整理,作书签使用,方便后期查阅。