2016-05-30 28 views
4

我想提高我的编程技能,我遇到了一个令人沮丧的问题,这可能是最好的解释一个例子:单身人士和服务定位器的真正替代品?

假设我在PHP中创建一个microCMS。这个microCMS有一个路由器类,负责路由。它还包含从中提取的URI和额外参数。

class Router{ 
    private $uri; 
    private $params; 
    ... 
    public function getRoute(){ ... } 
    ... 
    public function getParams(){ 
    return $this->params; 
    } 
    ... 
} 

我也有一个前端控制器,我通过一个新的路由器()对象。到目前为止,这么好,我可以访问我的前端控制器中的额外参数(通过$router->getParams();)。

class FrontController{ 
    private $controller; 
    private $view; 

    public function __construct(Router $router){ 
    $route = $router->getRoute(); 
    ... 
    $params = $router->getParams(); //Yay, I can get to the params here! 
    ... 
    $this->view = new View($route->getModel()); 
    ... 
    } 

现在,这里是它对我来说变得复杂。这个前端控制器构建一个视图。我希望这个View也能够访问路由器的功能(例如能够从中获取URI参数)。

class View{ 
    public function output(){ 
    //But how do I access the Router's params here...? 
    } 
} 

首先,最简单的解决方案似乎是使路由器进入一个单身或刚做的函数静态和简单的调用Router::getParams() ...但是,这是一个没有没有,因为反模式。

第二个显而易见的解决方案是将我的Router实例传递给View的构造函数。我想避免这种情况,因为我担心我的构造者会在某个地方变得巨大。我不知道还有多少其他类需要从视图中访问,我不希望它们不必要地混淆构造函数。这种恐惧是否合理?

另一种解决方案是使用服务定位器并在我的视图中调用类似$serviceLocator->getRouter()的东西。但是,显然,这也是一种反模式。

那么解决方案是什么?或者是我的CMS架构根本错误?

回答

2

FrontController使用Dependency Injection,这被认为是处理这种情况的最佳方式。因为你直接传递了这个类的实例,所以你不会创建一个单例中固有的一个global问题。

担心你的构造函数会变得臃肿是没有根据的。如果你需要依赖,那么你需要在某处注入它。你不必在你的构造函数中做这个,tho。你总是可以像

public function setRouter(Router $router) { 
    $this->router = $router; 
} 

并注入它就像那样。

如果你的类本身真的膨胀,那么你需要将它重构成子类。

+0

通过几个实例化级别注入路由器依赖关系(首先进入前端控制器,然后进入视图,然后谁知道我可能需要的其他位置......)不被认为是不好的做法? 我什么时候知道是时候将我的类重构为子类?何时存在太多的依赖关系? –

+1

不是。你注入的是同一个类,所以它会按照你所需要的注入次数。我的经验法则是,如果一个班级超过700行,你需要重构。至于太多的依赖......这取决于你在做什么 – Machavity