在A类中使用了B类的实例时,B对象的构造不是在A类某个方法中初始化的,而是在A类外部初始化之后以B类的对象传入进来。这个过程就是依赖注入。
这在我们PHP里感触不明显,觉得修改$config和修改$travel = new drive(60,1000)差别不到,一方面是便于管理,另一方面是PHP的非编译型的特性优势。如果用Java来实现,感触就非常明显了,比如程序已经打包了,只需要修改配置文件,就可以控制类的依赖关系了。起到了解耦的作用。
只要不是由内部生产(比如初始化、构造函数 __construct 中通过工厂方法、自行手动 new 的),而是由外部以参数或其他形式注入的,都属于依赖注入(DI)
1.原始代码:
class Superman { protected $power; public function __construct() { $this->power = new Fight(9, 100); } }
2.工厂模式:
class SuperModuleFactory { public function makeModule($moduleName, $options) { switch ($moduleName) { case 'Fight': return new Fight($options[0], $options[1]); case 'Force': return new Force($options[0]); case 'Shot': return new Shot($options[0], $options[1], $options[2]); } } }
class Superman { protected $power; public function __construct(array $modules) { // 初始化工厂 $factory = new SuperModuleFactory; // 通过工厂提供的方法制造需要的模块 foreach ($modules as $moduleName => $moduleOptions) { $this->power[] = $factory->makeModule($moduleName, $moduleOptions); } } } // 创建超人 $superman = new Superman([ 'Fight' => [9, 100], 'Shot' => [99, 50, 2] ]);
3.依赖注入:
interface SuperModuleInterface { /** * 超能力激活方法 * * 任何一个超能力都得有该方法,并拥有一个参数 *@param array $target 针对目标,可以是一个或多个,自己或他人 */ public function activate(array $target); }
/** * X-超能量 */ class XPower implements SuperModuleInterface { public function activate(array $target) { // 这只是个例子。。具体自行脑补 } } /** * 终极炸弹 (就这么俗) */ class UltraBomb implements SuperModuleInterface { public function activate(array $target) { // 这只是个例子。。具体自行脑补 } }
class Superman { protected $module; public function __construct(SuperModuleInterface $module) { $this->module = $module; } }
$superModule = new XPower; $superMan = new Superman($superModule);
4.ioc容器 - 更先进的工厂:
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 = []) { // 直接返回已保存的对应$abstract的对象 if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } // 执行脚本,生产指定$abstract, $parameters的对象 array_unshift($parameters, $this); return call_user_func_array($this->binds[$abstract], $parameters); } }
// 创建一个容器(后面称作超级工厂) $container = new Container; // 向该 超级工厂添加超人的生产脚本 $container->bind('superman', function($container, $moduleName) { return new Superman($container->make($moduleName)); }); // 向该 超级工厂添加超能力模组的生产脚本 $container->bind('xpower', function($container) { return new XPower; }); // 同上 $container->bind('ultrabomb', function($container) { return new UltraBomb; }); // ****************** 华丽丽的分割线 ********************** // 开始启动生产 $superman_1 = $container->make('superman', ['xpower']); $superman_2 = $container->make('superman', ['ultrabomb']); $superman_3 = $container->make('superman', ['xpower']); // ...随意添加