如果我的网站设计遵循以下依赖流:
处理程序类<;->;服务类<;->;映射器类->;模型类
处理程序接收请求,服务包含逻辑,映射器执行数据库查询并使用模型处理数据,而模型表示数据库中的单个记录.
理想情况下,您应该在相邻层上/从相邻层显式定义从属关系.因此,如果我更改特定的层,只有两个紧邻的层might会受到影响.
然而,我意识到我可能在使用一些糟糕的做法.具体地说,我让Service类调用Mapper类上的方法.Mapper类将返回Model类的一个实例.但是,如果我随后从Service类中调用Model类的方法,则现在Service类和Model类之间存在直接和隐式的依赖关系.
关于如何解决这个问题,我有几个 idea ,我将在下面概述.但我觉得肯定有更好的办法.所以我很好奇一般的共识是什么,避免这些隐式依赖情况,同时避免不必要的处理.
- 将空的Model实例注入到Service类中,以使依赖项显式.但这似乎很笨拙,没有考虑到多个记录的结果集.
- 将Model接口指定为该方法的Mapper接口中的返回类型.在我看来,这似乎是首选的方法.然而,当您必须返回多记录结果集时,情况就变得复杂了.在开始将结果用于实际的应用程序逻辑之前,我宁愿不要不必要地迭代Mapper类中的整个结果集.至少,对于几乎每个查询而言,这将是O(2n)时间复杂度.所以我刚刚返回了一个对象,它是一个\Iterable对象,并在Service类中迭代该对象(所以O(N)是Floor,而不是O(2n)).但这与存在对Model类的隐式依赖的情况相同.
我一直在try 找出是否有可能指定Iterable将迭代的对象的类型,就像您对数组所做的那样(IE:int[]
是一个整数数组).我能想到的最好办法就是创建一个特定于Model类的定制Iterator类.这是消除这些隐式依赖关系,同时避免不必要循环的首选方法吗?
非常感谢!
Edit based on feedback:个
我没有任何失败的代码,这个问题并不是特定于任何真实的代码.这个问题完全是关于一个抽象的问题.这就是为什么最初没有包括代码的原因.但根据反馈,我起草了以下内容,以帮助更清楚地说明目标情况.
只需忽略Handler类,不需要用它来说明概念,我只是想用它来描述总体 struct ,以便更容易地识别设计模式.
服务类别:
namespace App\Service;
class Service implements ServiceInterface
{
protected mapperInterface $mapper;
public function __construct(mapperInterface $mapper){
$this->mapper = $mapper;
}
public getAllRows() {
$iterator = $this->mapper->getAllRows();
while($iterator->valid()){
$current = $iterator->current();
// This line creates an implicit dependency on the Model class
$name = $current->getName();
$iterator->next();
}
}
}
映射器类: 命名空间App\Mapper;
class Mapper implements MapperInterface
{
protected modelInterface $modelPrototype;
public function __construct(modelInterface $model){
$this->modelPrototype = $model;
}
public getAllRows() : Iterator {
// Execute SQL then hydrate into an iterator over multiple "Model" objects into a variable ($resultSet in this case)
return $resultSet; // This is an Iterator instance of which each iteration contains a "Model" object.
}
}
Model类:
class Model implements ModelInterface
{
protected string $name;
public function getName() : string {
return $this->name;
}
public function setName(string $name) : void {
$this->name = $name;
}
}
具体地说,正是Service类中的此行在Service类和Model类之间创建了隐式依赖关系(通过Mapper类绕过传递依赖关系):
$name = $current->getName();
有两种方法可以纠正这一点,要么显式地显示依赖关系,要么首先消除依赖关系.我已经将我的 idea 列在了how条上,以实现这两个 Select .但我很好奇,对这种情况最常见的解决方案是什么.有没有其他我没有想过的解决这个问题的 Select 或方法?或者是我提出的 idea 之一,通常是首选的方法.