Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 设计一个服务容器:SRP,选择正确的创建模式并避免紧密耦合_Php_Oop_Design Patterns_Containers_Service Locator - Fatal编程技术网

Php 设计一个服务容器:SRP,选择正确的创建模式并避免紧密耦合

Php 设计一个服务容器:SRP,选择正确的创建模式并避免紧密耦合,php,oop,design-patterns,containers,service-locator,Php,Oop,Design Patterns,Containers,Service Locator,我正在编写自己的Laravel服务容器实现,以实践一些设计模式,然后制作一个私有的微框架 该类现在看起来是这样的: 类容器实现ContainerInterface { /** *合同的具体约束力。 * *@var数组 */ 受保护的$bindings=[]; /** *用于类实例化的参数列表。 * *@var数组 */ 受保护的$arguments=[]; /** *用于存储已构建或自定义设置的对象的容器存储。 * *@var数组 */ 受保护的$storage=[]; /** *返回服务的实例

我正在编写自己的Laravel服务容器实现,以实践一些设计模式,然后制作一个私有的微框架

该类现在看起来是这样的:

类容器实现ContainerInterface
{
/**
*合同的具体约束力。
*
*@var数组
*/
受保护的$bindings=[];
/**
*用于类实例化的参数列表。
*
*@var数组
*/
受保护的$arguments=[];
/**
*用于存储已构建或自定义设置的对象的容器存储。
*
*@var数组
*/
受保护的$storage=[];
/**
*返回服务的实例
*
*@param$name
*@返回对象
*@throws\ReflectionException
*/
公共函数get($name){
$className=(isset($this->bindings[$name])?$this->bindings[$name]:$name;
if(isset($this->storage[$className])){
返回$this->storage[$className];
}
返回$this->make($className);
}
/**
*创建类的实例
*
*@param$className
*@返回对象
*@throws\ReflectionException
*/
公共函数make($className){
$REBOJECT=new\ReflectionClass($className);
如果(!$REBOJECT->ISINSTATIABLE()){
抛出new\ReflectionException($className不可实例化);
}
$refConstructor=$refObject->getConstructor();
$refParameters=($refConstructor)?$refConstructor->getParameters():[];
$args=[];
//迭代构造函数参数,检查自定义定义的参数
//并构建$args数组
foreach($refParameters作为$refParameter){
$refClass=$refParameter->getClass();
$parameterName=$refParameter->name;
$parameterValue=
isset($this->arguments[$className][$parameterName])?$this->arguments[$className][$parameterName]
:(null!=$refClass?$refClass->name
:($refParameter->isOptional()?$refParameter->getDefaultValue()
:null));
//递归地获取类实例化所需的对象
$args[]=($refClass)?$this->get($parameterValue)
:$parameterValue;
}
$instance=$reObject->newInstanceArgs($args);
$this->storage[$className]=$instance;
返回$instance;
}
/**
*设定合同的具体实施
*
*@param$abstract
*@param$混凝土
*/
公共函数绑定($abstract,$concrete){
$this->bindings[$abstract]=$concrete;
}
/**
*设置用于类实例化的参数
*
*@param$className
*@param数组$arguments
*/
公共函数setArguments($className,array$arguments){
$this->arguments[$className]=$arguments;
}
}
它工作正常,但我清楚地看到
make()
方法违反了SRP。所以我决定将一个对象创建逻辑委托给一个单独的类

我遇到的一个问题是该类将与
容器
类紧密耦合。因为它需要访问
$bindings
$arguments
数组,以及
get()
方法。即使我们将这些参数传递给类,存储仍然保留在容器中。所以基本上所有的架构都是错误的,我们需要另外两个类:
StorageManager
ClassFactory
。或者可能是
ClassBuilder
ClassFactory
应该能够构建构造函数参数,还是需要另一个类-
ArgumentFactory


伙计们,你觉得怎么样?

为什么你说你的
make
方法违反了SRP?在我看来,容器只是一袋对象,它不应该能够创建它们。但也许我错了。是的,你是对的!但我不明白这个容器的用途。它是一个通用容器吗?基本上是服务定位器模式的实现。它应该替代构造函数依赖项注入。例如,在一个控制器操作中,我们可以得到一个像
$this->container->get(“Mailer”)
这样的服务,而不是将其注入构造函数中。看这个。据我所知,您需要一个“一个工厂适合所有人”的实现。这样做毫无意义。您更喜欢使用依赖项注入容器,如。