Php 设计一个服务容器:SRP,选择正确的创建模式并避免紧密耦合
我正在编写自己的Laravel服务容器实现,以实践一些设计模式,然后制作一个私有的微框架 该类现在看起来是这样的:Php 设计一个服务容器:SRP,选择正确的创建模式并避免紧密耦合,php,oop,design-patterns,containers,service-locator,Php,Oop,Design Patterns,Containers,Service Locator,我正在编写自己的Laravel服务容器实现,以实践一些设计模式,然后制作一个私有的微框架 该类现在看起来是这样的: 类容器实现ContainerInterface { /** *合同的具体约束力。 * *@var数组 */ 受保护的$bindings=[]; /** *用于类实例化的参数列表。 * *@var数组 */ 受保护的$arguments=[]; /** *用于存储已构建或自定义设置的对象的容器存储。 * *@var数组 */ 受保护的$storage=[]; /** *返回服务的实例
类容器实现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”)
这样的服务,而不是将其注入构造函数中。看这个。据我所知,您需要一个“一个工厂适合所有人”的实现。这样做毫无意义。您更喜欢使用依赖项注入容器,如。