可能重复:
Dependecy Hell - how does one pass dependencies to deeply nested objects
最近我一直在努力解决这个特殊问题。为了测试和管理原因,我认为将$ config这样的对象注入需要它的人是一个更好的选择。虽然在开始时它没关系,后来它开始污染代码。 例如: 对象A使用对象B来完成它的工作,对象B使用策略对象C,对象C使用对象D,它需要$ config对象。所以,我必须继续将$ config传递给整个链
在我的代码中,我有两个像这样的对象通过,这使得构造函数很大,有重复的代码,通常它闻起来有些错误。 我很感激任何帮助重构这种关系。
答案 0 :(得分:2)
而不是(伪代码作为一般建议)......
config <-- ...
A.constructor (config) {
this.foo = config.foo
this.bar = config.bar
this.objectB = createB (config)
}
B.constructor (config) {
this.frob = config.frob
this.objectC = createC (config)
}
C.constructor (config) {
this.frobnicate = config.frobnicate
this.objectD = createC (configD)
}
你应该只传递真正需要的东西:
config <-- ...
A.constructor (foo, bar, frob, frobnicate) {
this.foo = foo
this.bar = bar
this.objectB = createB (frob, frobnicate)
}
B.constructor (frob, frobnicate) {
this.frob = frob
this.objectC = createC (frobnicate)
}
C.constructor (frobnicate) {
this.frobnicate = frobnicate
}
让您的州尽可能在当地。全局状态是无限量调试恐怖场景的根源(因为我闻到你刚才面临的情况)。
或者,许多类不必知道它们的对象是什么样的,它们只对公共接口感兴趣。您可以应用依赖项反转,然后:
config <-- ...
objectC = createC (config.frobnicate)
objectB = createB (config.frob, objectC)
objectA = createA (config.foo, config.bar, objectB)
使用依赖性反转意味着让您的课程免于需要了解太多。例如,Car
无需了解Trailer
及其成分,只需了解CouplingDevice
:
trailer = createTrailer (...)
couplingDevice = createCouplingDevice (...)
car.install (couplingDevice)
couplingDevice.attach (trailer)
答案 1 :(得分:0)
我是否认为$ config包含......以及大部分应用程序所需的配置信息?如果是这样,听起来你应该考虑(普遍的)单身设计模式。
如果您还不熟悉它,那么这种技术在您的应用程序运行时只允许一个类的实例。这在维护应用程序范围的值时非常有用,因为您不会冒实例化第二个对象的风险;你也没有绕过物品的“副本”。
例如,请检查以下内容:
<?php
class Test {
private static $instance;
private function __construct() { } // Private constructor
static function instance() {
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
$a = Test::instance();
$b = Test::instance();
$a->property = 'abc';
var_dump($a->property);
var_dump($b->property);
?>
您将看到两个'实例'都包含值为'abc'的'property',因为它们实际上都是同一个实例。如果你已经熟悉这种技术,我很抱歉,但这听起来肯定是你要找的东西!
修改强>
如下所述,这仍然可以克隆。如果你真的想要防止这种情况发生,你必须覆盖魔术方法__clone()来阻止这种情况发生。然而,序列化观察只是迂腐。
答案 2 :(得分:0)
您似乎需要使用singleton或注册表模式。
单例由一个类(带有私有构造函数)组成,可以通过静态方法创建,以便在每次需要时获得相同的对象(原谅我的简化)。
遵循这个方案:
class Config {
static private instance=null;
private function __constructor() {
// do your initializzation here
}
static public function getInstance() {
if (self::instance==null) {
self::instance== new Config();
}
return self::instance;
}
// other methods and properties as needed
}
通过这种方式,您可以使用类似
的内容获取所需的对象$config = Config::getInstance();
没有在调用堆栈中传递它而不依赖于全局变量。
注册表具有类似的工作方案,但允许您创建一种注册表,因此需要提供对象的名称。