我知道它被认为是坏事:
$this->laptop->getKeyboard()->getTouchpad()->getLbutton();
或
$this->laptop->getKeyboard()->getCapslock()->isLedOn();
它解释为"我们不想要吨 - > - > - > - >" - 但我想让这个建筑物理,我的意思是它不能脱钩。我理解,如果架构师改变了,它必须在任何地方完成,但它不会发生。再说一次,如何解决这个问题?
答案 0 :(得分:6)
Demeter法则不依赖于依赖性 - > (或其他语言的点)。
例如,如果您有一个流畅的界面(方法返回此处),则该法律不适用。
您希望您的班级依赖于最少数量的其他班级。
如果你的班级依赖于其他10个班级,那么任何一个班级的改变都可以打破它。理解你班级的作用更难。测试这样的课程也很难。
如果你有$field->getDependency1()->getDependency2()
或$field->dependency1->dependency2
并不重要 - 你的代码仍然取决于其他两个类,并且知道dependency1的内部结构(它内部有dependency2)。
您可以使用tell don't ask principle解决问题。 在OOD中,您不希望使用仅包含数据的结构。您希望拥有知道如何处理其字段的对象。
例如,你可以重构:
$oldBalance = $bank->getAccount()->getBalance();
$bank->getAccount()->setBalance($oldBalance - $amount);
致:
$bank->withdraw($amount);
银行类:
function withdraw($amount) {
$this->account->withdraw($amount);
}
在帐户类中:
function withdraw($amount) {
$this->balance = $this->balance - $amount;
}
您有更多方法,但现在使用$ bank的代码,对帐户及其余额一无所知。您可以轻松地测试该类仅模拟$ bank字段。您还有更多可重复使用的代码。
答案 1 :(得分:6)
想象一下这个对话:
You: Hey Laptop, get me the I/O devices
Laptop: There you go
You: Hey IODevices, get me the keyboard
IODevices: There you go
You: Hey Keyboard, get me the touchpad
Keyboard: There you go
You: Hey Touchpad, I want to press your left button
Touchpad: Consider it done Boss!
男人,你是一个疯狂的电子迷,或者你是为了生活 - 你知道你的笔记本电脑的每一小块! ;)
VS。这样:
You: Hey Laptop, I want to press left button on the touchpad
// Laptop gets the job done
Laptop: Done Boss!
在第二次谈话中,在引擎盖下,
Laptop
调用其依赖关系IODevices
(您不需要了解它的任何内容),IODevices
调用其依赖关系Keyboard
(Latop
并不需要了解它),Keyboard
获取其依赖关系Touchpad
(IODevices
并不需要了解它 - 事实上它有点不好的例子,但是......你得到这个想法,然后在上面调用pressLeftButton()
。那就是说,你不关心细节,你要做的只是pressLeftButton
。您不需要知道Keyboard
和Touchpad
的关联方式,每种方法返回的内容等。您必须实现公共接口。
这让每个人都感到高兴,因为只要后者实现相同的界面,用KeyboardXyz
替换KeyboardAbc
时就不会有任何损失。