- 简单版的
<?php
interface SuperModuleInterface
{
public function activate(array $target);
}
class XPower implements SuperModuleInterface
{
public function activate(array $target)
{
// something
}
}
class UltraBomb implements SuperModuleInterface
{
public function activate(array $target)
{
// something
}
}
class Superman
{
protected $module;
public function __construct(SuperModuleInterface $module)
{
$this->module = $module;
}
}
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);
}
}
$container = new Container;
// 向该 超级工厂 添加 超人 的生产脚本
$container->bind('superman', function($container, $moduleName) {//call_user_func_array里的参数array_unshift里的参数
return new Superman($container->make($moduleName));
});
// 向该 超级工厂 添加 超能力芯片 的生产脚本
$container->bind('xpower', function($container) {
return new XPower;
});
// 同上
$container->bind('ultrabomb', function($container) {
return new UltraBomb;
});
// 开始启动生产
$superman = $container->make('superman', ['ultrabomb']);
echo "<pre>";var_dump($superman);
/*
输出
object(Superman)#5 (1) {
["module":protected]=>
object(UltraBomb)#6 (0) {
}
}
*/
- 通过反射 容器 实现自动实例化类
<?php
class Container{
protected $bindings = [];
public function bind($abstract, $concrete = null, $shared = false){
//echo 'start to bind: '.($abstract)."\n";
if(!$concrete instanceof Closure){
//echo 'get closure '. $abstract. ':' . $concrete."\n";
$concrete = $this->getClosure($abstract, $concrete);
// if($abstract == 'traveller'){
// var_dump($concrete);
// }
}
$this->bindings[$abstract] = compact('concrete', 'shared');//都是匿名函数
}
protected function getClosure($abstract, $concrete){
$x = function ($c) use($abstract, $concrete){
$method = ($abstract == $concrete) ? 'build' : 'make';//相同的话直接实例化
return $c->$method($concrete);
};
//var_dump($x);exit;
return $x;
}
public function make($abstract){//todo traveller Traveller Visit可以理解。为什么还有个Leg?因为Visit作为abstract后有个Leg
$concrete = $this->getConcrete($abstract);//注释1 那里注释了也可以运行,因为这里自动生成了$concrete $abstract
if($this->isBuildable($concrete, $abstract)){//todo 精华,用traveller代入make方法的$abstract里,一步步想 !!!!!!!!!!!!
$object = $this->build($concrete);
}else{
$object = $this->make($concrete);
}
return $object;
}
protected function isBuildable($concrete, $abstract){
return $concrete === $abstract || $concrete instanceof Closure;
}
protected function getConcrete($abstract){
if(!isset($this->bindings[$abstract])){
return $abstract;
}
return $this->bindings[$abstract]['concrete'];
}
public function build($concrete){
if($concrete instanceof Closure){
return $concrete($this);
}
$reflector = new ReflectionClass($concrete);
if(!$reflector->isInstantiable()){
echo $message = "Target {$concrete} is not instantiable.";
}
$constructor = $reflector->getConstructor();
if(is_null($constructor)){
return new $concrete;
}
$dependencies = $constructor->getParameters();//构造函数里的参数
$instances = $this->getDependencies($dependencies);
return $reflector->newInstanceArgs($instances);
}
protected function getDependencies($parameters){
$dependencies = [];
foreach($parameters as $parameter){
$dependency = $parameter->getClass();
if(is_null($dependency)){
$dependencies[] = null;
}else{
$dependencies[] = $this->resolveClass($parameter);
}
}
return (array)$dependencies;
}
protected function resolveClass(ReflectionParameter $parameter){//解决构造函数里的那个Visit
// $parameter->getClass()->name就是Visit
return $this->make($parameter->getClass()->name);
}
}
interface Visit{
public function go();
}
class Train implements Visit{
public function go(){
echo 'go to by train';
}
}
class Leg implements Visit{
public function go(){
echo 'go to by Leg';
}
}
class Traveller{
protected $trafficTool;
public function __construct(Visit $trafficTool)
{
$this->trafficTool = $trafficTool;
}
public function visitTibet(){
$this->trafficTool->go();
}
}
class jackC{
public function __construct($what){
echo 'construct ' . $what."\n";
}
public function visitTibet(){
echo 'this is made by jack.';
}
}
$app = new Container();
$app->bind('Visit', 'Leg');
$app->bind('traveller', 'Traveller');//去掉这行也可以运行???因为 class Abc{} $obj = new abc(); 也可以。加的原因是在注释1
//$app->bind('traveller', function(){//方法一。这里的bind可以直接bind一个匿名函数。
// return new jackC();
//});
//$app->bind('traveller', 'jackC');//方法二。todo,如何传参
$tra = $app->make('traveller');
$tra->visitTibet();
2.1 解释说明2
打印
string(9) "traveller"
string(13) "--start build"
string(37) "---start, traveller-Traveller to make"
string(28) "Traveller 也是buildAble的"
string(9) "Traveller"
string(13) "--start build"
string(34) "--build not Closure ==== Traveller"
string(5) "Visit"
string(13) "--start build"
string(27) "---start, Visit-Leg to make"
string(3) "Leg"
string(13) "--start build"
string(28) "--build not Closure ==== Leg"
go to by Leg
<?php
class Container{
protected $bindings = [];
public function bind($abstract, $concrete = null, $shared = false){
//echo 'start to bind: '.($abstract)."\n";
if(!$concrete instanceof Closure){
//echo 'get closure '. $abstract. ':' . $concrete."\n";
$concrete = $this->getClosure($abstract, $concrete);
// if($abstract == 'traveller'){
// var_dump($concrete);
// }
}
$this->bindings[$abstract] = compact('concrete', 'shared');//都是匿名函数
}
protected function getClosure($abstract, $concrete){
$x = function ($c) use($abstract, $concrete){
$method = ($abstract == $concrete) ? 'build' : 'make';//相同的话直接实例化
var_dump('---start, ' . $abstract . '-' . $concrete. ' to ' . $method);
return $c->$method($concrete);
};
//var_dump($x);exit;
return $x;
}
/*
* 先是make的时候traveller,进去了
* getClosure()里traveller和Travellers不一致,所以make
* */
public function make($abstract){//todo traveller Traveller Visit可以理解。为什么还有个Leg?因为Visit作为abstract后有个Leg
$concrete = $this->getConcrete($abstract);//注释1 那里注释了也可以运行,因为这里自动生成了$concrete $abstract
if($this->isBuildable($concrete, $abstract)){//todo 精华,用traveller代入make方法的$abstract里,一步步想 !!!!!!!!!!!!
var_dump($abstract);
/*
* //这里var_dump($abstract)打印的顺序是
* string(9) "traveller"
string(9) "Traveller"
string(5) "Visit"
string(3) "Leg"
,但是放到build后面,就反了,奇怪!!!!!!!!!!!!!!
* */
$object = $this->build($concrete);
}
return $object;
}
protected function isBuildable($concrete, $abstract){
if($concrete == 'Traveller' && $abstract == 'Traveller'){
var_dump('Traveller 也是buildAble的');
}
return $concrete === $abstract || $concrete instanceof Closure;
}
protected function getConcrete($abstract){
if(!isset($this->bindings[$abstract])){
return $abstract;
}
return $this->bindings[$abstract]['concrete'];
}
public function build($concrete){
var_dump('--start build');
if($concrete instanceof Closure){
return $concrete($this);
}else{
var_dump('--build not Closure ==== ' . $concrete);
}
$reflector = new ReflectionClass($concrete);
if(!$reflector->isInstantiable()){
echo $message = "Target {$concrete} is not instantiable.";
}
$constructor = $reflector->getConstructor();
if(is_null($constructor)){
return new $concrete;
}
$dependencies = $constructor->getParameters();//构造函数里的参数
//$dependencies 是构造函数里的参数,这里是$trafficToollll
$instances = $this->getDependencies($dependencies);
return $reflector->newInstanceArgs($instances);
}
protected function getDependencies($parameters){
$dependencies = [];
foreach($parameters as $parameter){
$dependency = $parameter->getClass();
if(is_null($dependency)){
$dependencies[] = null;
}else{
//通过Visit $trafficToollll ,解析出来是绑定过的Leg
$dependencies[] = $this->resolveClass($parameter);
}
}
return (array)$dependencies;
}
protected function resolveClass(ReflectionParameter $parameter){//解决构造函数里的那个Visit
// $parameter->getClass()->name就是Visit
return $this->make($parameter->getClass()->name);
}
}
interface Visit{
public function go();
}
class Train implements Visit{
public function go(){
echo 'go to by train';
}
}
class Leg implements Visit{
public function go(){
echo 'go to by Leg';
}
}
class Traveller{
protected $trafficTool;
public function __construct(Visit $trafficToollll)
{
$this->trafficTool = $trafficToollll;
}
public function visitTibet(){
$this->trafficTool->go();
}
}
class jackC{
public function __construct($what){
echo 'construct ' . $what."\n";
}
public function visitTibet(){
echo 'this is made by jack.';
}
}
echo "<pre>";
$app = new Container();
$app->bind('Visit', 'Leg');
$app->bind('traveller', 'Traveller');//去掉这行也可以运行???因为 class Abc{} $obj = new abc(); 也可以。加的原因是在注释1
//$app->bind('traveller', function(){//方法一。这里的bind可以直接bind一个匿名函数。
// return new jackC();
//});
//$app->bind('traveller', 'jackC');//方法二。todo,如何传参
$tra = $app->make('traveller');
$tra->visitTibet();
网友评论