依赖注入 简介
依赖注入 设计模式之一/方法
又名 控制反转 降低耦合度
课前准备知识
- interface
- implements
- Closure
用于代表 匿名函数 的类 - instanceof
用于确定一个 PHP 变量是否属于某一类 class 的实例
来确定一个变量是不是继承自某一父类的子类的实例 - __Construct()
- call_user_func_array
调用回调函数,并把一个数组参数作为回调函数的参数 - array_unshift
在数组开头插入一个或多个单元
没有用依赖注入和控制反转的时候
<?php
class dog{
function eat(){
echo "dog to eat".PHP_EOL;
}
}
class cat{
function eat(){
echo "cat to eat".PHP_EOL;
}
}
class menu{
function forEat(){
$dog = new dog();
$dog->eat();
$cat = new cat();
$cat->eat();
// to kill
echo "kill for eat".PHP_EOL;
}
}
初步实现依赖注入
<?php
interface animal{
function eat();
}
class dog implements animal{
function eat(){
echo "dog to eat".PHP_EOL;
}
}
class cat implements animal{
function eat(){
echo "cat to eat".PHP_EOL;
}
}
class menu{
protected $obj = '';
function __construct(animal $a){
$this->obj = $a;
}
function forEat(){
$this->obj->eat();
}
}
$dog = new dog;
$m = new menu($dog);
$m->forEat();
终结版
<?php
interface animal{
function eat();
}
class dog implements animal{
function eat(){
echo "dog to eat".PHP_EOL;
}
}
class cat implements animal{
function eat(){
echo "cat to eat".PHP_EOL;
}
}
class snake implements animal{
protected $name = '';
function __Construct($name){
$this->name = $name;
}
function eat(){
echo $this->name." snake to eat".PHP_EOL;
}
}
class menu{
protected $obj = '';
function __construct(animal $a){
$this->obj = $a;
}
function forEat(){
$this->obj->eat();
}
}
class Container{
protected $binds;
protected $instances;
public function bind($abstract,$concrete){
if ($concrete instanceof Closure) { // 判断是不是闭包化
$this->binds[$abstract] = $concrete;
} else {
$this->instances[$abstract] = $concrete;// 正常实例化
}
}
public function make($abstract,$parameters=[]){
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
array_unshift($parameters, $this);
return call_user_func_array($this->binds[$abstract], $parameters);
}
}
$obj = new Container;
$dog = new dog();
$obj->bind('Dog',$dog);
$want_eat = $obj->make('Dog');
$want_eat->eat();
$snake = new snake('neinei');
$obj->bind('Snake',$snake);
$snake_eat = $obj->make('Snake');
$snake_eat->eat();
$obj->bind('Cat',function(){
return new cat;
});
$cat_eat = $obj->make('Cat');
$cat_eat->eat();