我知道它被认为是不好的:
$this->laptop->getKeyboard()->getTouchpad()->getLbutton();
或者
$this->laptop->getKeyboard()->getCapslock()->isLedOn();
它被解释为“我们不想要大量的 -> -> -> ->” - 但我想让这个结构物理化,我的意思是它不能解耦。我知道如果架构师发生变化,它必须在任何地方完成,但它不会发生。再说一次,如何解决这个问题?
我知道它被认为是不好的:
$this->laptop->getKeyboard()->getTouchpad()->getLbutton();
或者
$this->laptop->getKeyboard()->getCapslock()->isLedOn();
它被解释为“我们不想要大量的 -> -> -> ->” - 但我想让这个结构物理化,我的意思是它不能解耦。我知道如果架构师发生变化,它必须在任何地方完成,但它不会发生。再说一次,如何解决这个问题?
得墨忒耳法则是关于依赖而不是 -> (或其他语言中的点)。
例如,如果您有一个流畅的接口(其中方法返回 this),则此法律不适用。
您希望您的班级依赖最少数量的其他班级。
如果您的课程依赖于其他 10 个课程,那么其中任何一个课程的更改都会破坏它。很难理解你的班级是做什么的。也很难测试这样的课程。
如果你有$field->getDependency1()->getDependency2()
或者$field->dependency1->dependency2
- 你的代码仍然依赖于另外两个类并且知道dependency1的内部结构(它内部有dependency2),这并不重要。
你可以用告诉不问原则来解决你的问题。在 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 的代码对 Account 及其余额一无所知。您可以轻松地测试仅模拟 $bank 字段的类。您还有更多可重用的代码。
想象一下这段对话:
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!
伙计,你是个电子迷,或者你是为了生活而做的——你知道你笔记本电脑的每一小块!;)
与这个:
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
。