依赖注入的核心功能就是将所依赖单元的实例化,放到类的外面进行。
例如:
interface C
{
public function aaa();
}
class B implements C
{
public function aaa()
{}
}
class A
{
public function run()
{
$object = new B();
$object->aaa();
}
}
在此例中,类A就依赖于B类,B类的实例化是在类A的内部实现的,这样A和B的耦合度过高。所以需要将类B的实例化移动到外部实现,然后注入到类的内部。
注入的方式分为两种:构造方法注入和属性注入
1.构造方法注入。
我们改造下类A
class A
{
public $object;
public function __construct($object)
{
$this->object = $object;
}
public function run()
{
$this->object->aaa();
}
}
在实例化类A时,我们传入一个类B的实例化,赋值给属性object.这样run方法运行时直接调用属性object的方法即可。object对象可以在实例化过程中更改。
2.属性注入
class A
{
public $object;
public funciton setObject($object)
{
$this->object = $object;
}
public function run()
{
$this->object->aaa();
}
}
属性注入可以在A实例化后,也可以随时改变属性object所持有的对象,这样就更加灵活了。
现在,我们提供一个Container对象,它可以在你索取某一个类的实例时,自动创建并返回一个实例。
联系之前的关于注入的知识,属性注入是在类实例化之后的事,而我们的Container要解决的是如何实例化一个类的事,所以它只需要关注构造注入中的依赖就可以了。
要实现一个Container对象,需要具备以下功能。
属性:
1.defineMap 存放注册的依赖关系
2.paramsMap 存放注册时提供的参数
3.dependencyMap 存放类构造函数的依赖关系
4.reflectionMap 存放类的放射实例
5.singletonMap 存放类的单例对象
方法:
1.注册依赖关系的方法
2.创建类的方法
3.其中创建类必须解析构造方法中的依赖,所以要有一个解析构造方法依赖的方法
4.解析了构造方法依赖,还必须有解决这个依赖的方法
5.注册依赖关系时,不仅有类,还会传递回调函数,已实例化的对象等;我们也需要对这些进行支持,所以会有一个统一的返回索要实例的方法其中不仅包含创建类,还包含调用回调函数等。
ok,今儿个先到这,欲知后事如何,且听下回分解……
github源码:https://github.com/2lovecode/tank