第一种方式,普通方式实现模拟操作数据库方法
# 第一种写法,耦合度高
# 模拟db操作数据库的类
class dbMysql
{
public function query()
{
return " 这是 db操作mysql的类";
}
}
# controller是需要dbmysql才能操作数据库
class Controller
{
# 定义一个私有的变量 用来存放数据库操作对象
private $db;
# 构造函数
public function __construct()
{
# 创建对象实例,同时传递到预定义好的变量中
$this->db = new dbMysql();
}
# 操作方法,因为构造方法先执行,可以通过db中的对象访问dbmysql中的方法
public function action()
{
return $this->db->query();
}
}
# 创建这个实例
$c = new Controller();
echo $c->action();
# 这种方法简单同时方便操作,但是不好维护,假设要操作多个数据库的方法呢。所以控制反转和依赖注入就出现了。都是为了简化操作,其实只是换了种说法而已。
第二种方式:控制反转和依赖注入
class dbMysql
{
public function query()
{
return " 这是 db操作mysql的类";
}
}
# controller是需要dbmysql才能操作我们的数据库
class Controller
{
private $db;
# 在这里获取创建好的对象实例,并赋值传递给预定义好的属性
public function __construct($dbMysql)
{
$this->db = $dbMysql;
}
public function action()
{
return $this->db->query();
}
}
# 与第一种方式相比,简单来说,是将原本在类中创建对象的方式,提取到类的外部中,然后在传递到类中,这种就是控制反转,
# IOC控制反转:将原本在类中方法的依赖关系,提取到了外部管理,
$db = new dbMysql();
# DI依赖注入:将在外部中创建的对象实例,传递到类中,就称之为依赖注入
$c = new Controller($db);
echo $c->action();
那么是什么是控制反转?什么是依赖注入?
控制反转:将原本在类中要创建对象的实例,提取到了类外,在外部负责管理。
依赖注入:就是将在类的外部中创建的对象实例,传递到类中。
第三种方式:容器
# 创建一个dbmysql类
class dbMysql
{
public function query()
{
return " 这是 db操作mysql的类";
}
}
# 创建一个dbredis类
class dbRedis
{
public function query()
{
return " 这是 db操作redis的类";
}
}
# controller是需要dbmysql才能操作我们的数据库
class Controller
{
private $db;
public function __construct($dbMysql)
{
$this->db = $dbMysql;
}
public function action()
{
return $this->db->query();
}
}
/*
创建容器类,神秘的controlle类
吧controller 以及dbmysql创建实例的过程交给container
*/
class Container
{
# 绑定实例的容器 数组
private $bind = [];
/*
@param string $key 容器的标识
@param closure $value 创建容器方法
*/
# 创建容器
# Closure php中的匿名类,用来接受闭包函数,如果在传递的时候直接传递的是先创建对象,在传递到类中则不需要闭包
public function bind($key,Closure $value)
{
# key 就是你传递的容器的表述,
# value 就是传递的创建的对象实例
$this->bind[$key] = $value;
}
# 获取容器的实例
# @param string $key 容器的下表
# @return $object 容器的实例
public function make($key)
{
#
$object = $this->bind[$key];
return $object();
}
}
# 创建容器类
$app = new Container();
# 传递一个mysql表示下表key是mysql,使用闭包函数传递到容器中,这时候就创建的了对象的实例
$app->bind('mysql',function(){
return new dbMysql();
# 可以直接切换对象实例来调用不同的类,
# return new dbRedis();
});
# 创建控制器实例,传递一个controller下标,来标识当前是什么对象
$app->bind('controller',function() use ($app) {
# 在这时传递对象的时候,需要使用use 将类外的容器类的对象实例传递到这个闭包函数中
return new Controller($app->make('mysql'));
});
# 然后由于上方已经传递好的对应的对象的实例,我们可以在这里直接调用这个make方法,但是需要传递key,这个key就是上方的下标。
echo $app->make('controller')->action();
什么是容器类?
简单来讲,容器类就是代替了我们在去,频繁的去创建对象,只需要在传递的时候将类名改掉,解耦性就大大提高,方便维护,只需要修改相应的类名就可以调用不同的方法。
这是我今天学习之后对ioc、di、容器的一个简单的认知,感觉还是认知的不够简单。