Dependency Injection Containers 的基本功能:
- Container 管理对象实例化到配置的过程
- 对象本身不知道自己是由 Container 管理的,对 Container 一无所知。
这就是为什么 Container 能够管理任何 PHP 对象。 对象使用 DI 来管理依赖关系非常好,但不是必须的。
i
<?php
function info($msg){
echo $msg;
}
class LogToFile {
public function execute($message) {
info('log the message to a 美羊羊 :'.$message);
}
}
class UseLogger {
protected $logger;
public function __construct(LogToFile $logger) {
$this->logger = $logger;
}
public function show() {
$user = '小灰灰';
$this->logger->execute($user);
}
}
$useLogger = new UseLogger(new LogToFile());
$useLogger->show();
ii
A
<?php
function info($msg){
echo $msg;
}
class LogToFile {
public function execute($message) {
info('log the message to a 美羊羊 :'.$message);
}
}
class LogToDD {
public function execute($message) {
info('log the message to 喜羊羊 :'.$message);
}
}
class UseLogger {
protected $logger;
public function __construct(LogToFile $logger) {
$this->logger = $logger;
}
public function show() {
$user = '小灰灰';
$this->logger->execute($user);
}
}
$useLogger = new UseLogger(new LogToFile());
$useLogger->show();
B
<?php
function info($msg){
echo $msg;
}
class LogToFile {
public function execute($message) {
info('log the message to a 美羊羊 :'.$message);
}
}
class LogToDD {
public function execute($message) {
info('log the message to 喜羊羊 :'.$message);
}
}
class UseLogger {
protected $logger;
public function __construct(LogToDD $logger) {
$this->logger = $logger;
}
public function show() {
$user = '小灰灰';
$this->logger->execute($user);
}
}
$useLogger = new UseLogger(new LogToDD());
$useLogger->show();
iii
<?php
function info($msg){
echo $msg;
}
interface Logger {
public function execute($message);
}
class LogToFile implements Logger {
public function execute($message) {
info('log the message to a 美羊羊 :'.$message);
}
}
class LogToDD implements Logger {
public function execute($message) {
info('log the message to 喜羊羊 :'.$message);
}
}
class UseLogger {
protected $logger;
public function __construct(Logger $logger) {
$this->logger = $logger;
}
public function show() {
$user = '小灰灰';
$this->logger->execute($user);
}
}
$useLogger = new UseLogger(new LogToFile());
$useLogger->show();
echo '<br>';
$useLogger = new UseLogger(new LogToDD());
$useLogger->show();
终极版
<?php
function info($msg){
echo $msg;
}
interface Logger {
public function execute($message);
}
class LogToFile implements Logger {
public function execute($message) {
info('log the message to a 美羊羊 :'.$message);
}
}
class LogToDD implements Logger {
public function execute($message) {
info('log the message to 喜羊羊 :'.$message);
}
}
class UseLogger {
protected $logger;
public function __construct(Logger $logger) {
$this->logger = $logger;
}
public function show() {
$user = '小灰灰';
$this->logger->execute($user);
}
}
class SimpleContainer {
// 用于存储所有绑定 key-value
protected static $container = [];
public static function bind($name, Callable $resolver) {
static::$container[$name] = $resolver;
}
public static function make($name) {
if(isset(static::$container[$name])){
$resolver = static::$container[$name] ;
return $resolver();
}
throw new Exception("Binding does not exist in container");
}
}
SimpleContainer::bind(Logger::class, function () {
return new LogToDD();
});
$useLogger3 = new UseLogger(SimpleContainer::make(Logger::class));
$useLogger3->show();
示例
<?php
interface SuperModuleInterface{
public function activate(array $target);
}
class Superman
{
protected $module;
/**
* Superman constructor.
* @param SuperModuleInterface $module
* 通过构造器 注入依赖
*/
public function __construct(SuperModuleInterface $module)
{
$this->module = $module;
}
public function show(array $target){
$this->module->activate($target);
}
}
class PowerA implements SuperModuleInterface
{
public function activate(array $target)
{
echo '<pre>'. __METHOD__;
print_r(func_get_args());
}
}
class PowerB implements SuperModuleInterface
{
public function activate(array $target)
{
echo '<pre>'. __METHOD__;
print_r(func_get_args());
}
}
class Container
{
protected $binds;
protected $instances;
/**
* @param $abstract
* @param $concrete
* 把代词 绑定到容器里,为后续make
*/
public function bind($abstract, $concrete)
{
if ($concrete instanceof Closure) {
$this->binds[$abstract] = $concrete;
} else {
$this->instances[$abstract] = $concrete;
}
}
/**
* @param $abstract
* @param array $parameters
* @return mixed
* 创建对象
*/
public function make($abstract, $parameters = [])
{
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
// 把容器对象$this,放到参数数组第一个元素。为call_user_func_array使用
array_unshift($parameters, $this);
// 这里$this->binds[$abstract] 绑定的闭包函数, 执行函数参数是$parameters
return call_user_func_array($this->binds[$abstract], $parameters);
}
}
// 创建一个容器(后面称作超级工厂)
$container = new Container;
// 向该 超级工厂添加超能力模组的生产脚本
$container->bind('powerA', function($container) {
return new PowerA;
});
// 同上
$container->bind('powerB', function($container) {
return new PowerB;
});
// 向该 超级工厂添加超人的生产脚本
$container->bind('superman', function($container, $moduleName) {
return new Superman($container->make($moduleName));
});
echo "<pre>";
// 开始启动生产
$superman_1 = $container->make('superman', ['powerA']);
$superman_1->show(['a' => 1]);
$superman_2 = $container->make('superman', ['powerB']);
$superman_2->show(['b' => 1]);
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。