我理解的服务容器就是一个自动产生类的工厂。
<?php
/**
* 为了约束我们先定义一个消息接口
* Interface Message
*/
interface Message{
public function seed();
}
/**
* 有一个发送邮件的类
* Class SeedEmail
*/
class SeedEmail implements Message
{
public function seed()
{
return 'seed email';
// TODO: Implement seed() method.
}
}
/**
*新增一个发送短信的类
* Class SeedSMS
*/
class SeedSMS implements Message
{
public function seed()
{
return 'seed sms';
// TODO: Implement seed() method.
}
}
/**
* 这是一个简单的服务容器
* Class Container
*/
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);
}
}
//创建一个消息工厂
$message = new Container();
//将发送短信注册绑定到工厂里面
$message->bind('SMS',function (){
return new SeedSMS();
});
//将发送邮件注册绑定到工厂
$message->bind('EMAIL',function (){
return new SeedEmail();
});
//需要发送短信的时候
$SMS = $message->make('SMS');
$SMS->seed();
container是一个简单的服务容器里面有bind,make两个方法
bind是向容器中绑定服务对象。make则是从容器中取出对象。
bind
在bind方法中需要传入一个 concrete 我们可以传入一个实例对象或者是一个闭包函数。
可以看到我这全使用的是闭包函数,其实也可以这样写
$sms = new SeedSMS();
$message->bind('SMS',$sms);
后面这种写法与闭包相比的区别就是我们需要先实例化对象才能往容易中绑定服务。而闭包则是我们使用这个服务的时候才去实例化对象。可以看出闭包是有很多的优势的。
make
make方法就从容器中出去方法。里面首先判断了instances变量中是否有当前以及存在的服务对象,如果有直接返回。如果没有那么会通过 call_user_func_array返回一个对象。call_user_func_array的使用可以查看
PHP 中 call_user_func 的使用