首页 > 其他分享 >控制反转(IOC)与依赖注入(DI)模式解析及实践

控制反转(IOC)与依赖注入(DI)模式解析及实践

时间:2024-08-06 11:30:37浏览次数:11  
标签:依赖 DI db Controller DbMysql 解析 IOC public

本文由 ChatMoney团队出品

在软件开发中,控制反转(Inversion of Control,简称IOC)和依赖注入(Dependency Injection,简称DI)是两种常用的设计模式,它们旨在降低组件间的耦合度,提高代码的可维护性和灵活性。

一、控制反转(IOC)模式

控制反转是将组件间的依赖关系从程序内部提到外部来管理。在传统的程序设计中,我们通常在类内部直接实例化其所依赖的类,这样类与类之间的耦合度较高。例如:

class DbMysql {
    public function query(){}
}

class Controller {
    public $db;
    public function __construct() {
        $this->db = new DbMysql();
    }
    public function action() {
        $this->db->query();
    }
}

$c = new Controller();$c->action();

在这个例子中,Controller类对DbMysql类产生了依赖。如果DbMysql类的构造函数发生变化,或者我们需要替换为另一个数据库类(如DbOracle),那么Controller类也需要相应地修改。这种方式使得代码的耦合度较高,不利于维护和扩展。

二、依赖注入(DI)模式

依赖注入是指将组件的依赖通过外部以参数或其他形式注入。通过依赖注入,我们可以将组件的创建过程与使用过程分离,降低耦合度。以下是一个依赖注入的示例:

class Controller {
    public $db;
    public function __construct($dbMysql) {
        $this->db =$dbMysql;
    }
    public function action() {
        $this->db->query();
    }
}

$db = new DbMysql();$c = new Controller($db);$c->action();

在这个例子中,Controller类不再负责实例化DbMysql,而是通过构造函数将DbMysql的实例作为参数传入。这样,Controller类只需关注如何使用DbMysql类,而无需关心其创建过程。

三、IOC容器实践

虽然依赖注入降低了耦合度,但如果项目中有很多类,手动管理这些依赖关系仍然很繁琐。这时,我们可以使用IOC容器来简化这个过程。

以下是一个简单的IOC容器实现:

class Container {
    public $bindings = [];
    public function bind($key,$value) {
        $this->bindings[$key] = $value;
    }
    public function make($key) {
        $concrete =$this->bindings[$key];
            return $concrete();
    }
}

$app = new Container();
    $app->bind('db', function () {
        return new DbMysql();
});
$db =$app->make('db');

在这个IOC容器中,我们通过bind方法将类名与闭包函数绑定,然后在需要实例化类时,通过make方法调用闭包函数。

四、结合反射优化IOC容器

为了进一步简化依赖注入过程,我们可以引入PHP的反射机制,让IOC容器自动解析类的依赖关系并注入。以下是结合反射的IOC容器实现:

class Container {
    // ...(省略其他代码)

    public function build($className) {
        $reflection = new ReflectionClass($className);
        $constructor =$reflection->getConstructor();
        if (is_null($constructor)) {
            return new $className;
        } else {
            $params =$constructor->getParameters();
            $dependencies = [];
            foreach ($params as$param) {
                $dependencies[] =$this->make($param->getClass()->name);
            }
            return $reflection->newInstanceArgs($dependencies);
        }
    }
}

// 使用IOC容器
$app = new Container();$app->bind('SMysql', 'DbMysql');
$app->bind('SRedis', 'DbRedis');$app->bind('controller', 'Controller');
$controller =$app->make('controller');
$controller->action();

在这个例子中,我们定义了接口SMysqlSRedis,以及对应的实现类DbMysqlDbRedisController类依赖于这两个接口。通过IOC容器,我们只需简单地将类名与接口绑定,容器会自动解析依赖关系并注入。

总结:

通过控制反转和依赖注入,我们能够有效地降低代码耦合度,提高代码的可维护性和扩展性。IOC容器进一步简化了依赖注入的过程,使得我们在实际开发中能够更加专注于业务逻辑的实现。

关于我们

本文由ChatMoney团队出品,ChatMoney专注于AI应用落地与变现,我们提供全套、持续更新的AI源码系统与可执行的变现方案,致力于帮助更多人利用AI来变现,欢迎进入ChatMoney获取更多AI变现方案!

标签:依赖,DI,db,Controller,DbMysql,解析,IOC,public
From: https://www.cnblogs.com/ChatMoney/p/18344796

相关文章

  • Codeforces Round 963 (Div. 2)
    A.QuestionMarks题目大意有4n道题,每道题有4个选项,且正确答案中每个选项各占有n个。给定一个字符串s,s中ABCD分别代表4个选项,?代表放弃这道题,求可能的最大正确数解题思路统计每个选项的出现次数,假设每次选的都对,即ans+=min(x,n)点击查看代码#include<bits/stdc++.h>usi......
  • Codeforces Round 963 (Div. 2)
    CodeforcesRound963(Div.2)A对A,B,C,D的数量和\(n\)取个\(\min\)相加B只有奇数或只有偶数答案为\(0\),否则,只能把所有的偶数改为奇数,因为不可能把所有奇数改为偶数。然后就是改的大小问题了。考虑找到最大的奇数,然后把偶数从小到大依次修改。C显然对\(2k\)......
  • Educational Codeforces Round 168 (Rated for Div. 2)
    没有时间参赛直接补几道简单题吧~B.MakeThreeRegions题意:给一个2行的字符串,有block和其他东西,问把一个位置变成block让联通的部分变成3个部分,有多少种方法思路:找规律,找所哟符合条件的块即可voidsolve(){ intn; cin>>n; array<string,2>s; cin>>s[0]>>s[1];......
  • 抖音短视频矩阵系统源码部署/技术应用开发(流程全解析)
     应用场景:抖音矩阵系统源码开发搭建/短视频矩阵号系统源码开发搭建/ 抖音seo矩阵系统源码开发搭建等。抖音短视频矩阵系统源码开发对服务商有哪些要求?企业在选择服务商时,无论是考虑自用还是考虑加盟服务商,都要考评服务商是否有相关开发资质,能力证明等,除此之外,功能的......
  • DASCTF 2023 & 0X401七月暑期挑战赛 MyPicDisk
    打开题目是个登录框这里是XXE盲注boogipop师傅的盲注脚本importrequestsimporttimeurl='http://6562827c-cc7e-4a5e-818d-97f9064dfce0.node4.buuoj.cn:81/index.php'strs='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'flag=''......
  • Android开发 - DialogFragment 类解析
    DialogFragment是什么DialogFragment是一种用于显示对话框的工具,同时它也是一个抽象类。在Android应用中,对话框是一种小窗口,通常用于显示重要信息或提示用户进行某些操作。通过使用DialogFragment,我们可以在应用中方便地显示和管理对话框DialogFragment的好处使用Dialo......
  • Androidstudio开发,ListView实现通讯录联系人列表( 四)
    文章目录1.涉及到的技术点2.发环境3.需求分析4.实现步骤5.代码实现全部过程6.效果图7.其它资料学习1.涉及到的技术点数据库SQLite的使用列表控件ListView的使用ListView事件监听适配器BaseAdapter的使用线性布局LinearLayoutCompat的使用2.发环境开发工具......
  • DyFusion:基于动态融合的交叉注意三维目标检测 论文解析
    目录概况创新点详解1、跨注意力动态融合 Cross-AttentionDynamicFusion(1)特征提取(2)体素特征编码(3)BEV特征提取(4)特征动态融合①线性变换②对Q(BEV特征)和K(图像特征)进行点积运算③Softmax运算④特征加权融合⑤将计算出来的特征与图像原特征进行连接 2、同步数......
  • Redis可以通过以下几种方式来避免内存溢出
    Redis可以通过以下几种方式来避免内存溢出:设置最大内存限制:可以使用maxmemory配置项来限制Redis的最大内存使用量。当Redis的内存占用超过了设置的最大内存限制时,Redis会根据所配置的内存策略来处理数据,例如删除最近最少使用的键或者拒绝写入请求。使用内存淘汰策略:当......
  • redis如何避免内存溢出
    Redis可以通过以下几种方式来避免内存溢出:设置最大内存限制:可以使用maxmemory配置项来限制Redis的最大内存使用量。当Redis的内存占用超过了设置的最大内存限制时,Redis会根据所配置的内存策略来处理数据,例如删除最近最少使用的键或者拒绝写入请求。使用内存淘汰策略:当......