0

我知道它被认为是不好的:

$this->laptop->getKeyboard()->getTouchpad()->getLbutton();

或者

$this->laptop->getKeyboard()->getCapslock()->isLedOn();

它被解释为“我们不想要大量的 -> -> -> ->” - 但我想让这个结构物理化,我的意思是它不能解耦。我知道如果架构师发生变化,它必须在任何地方完成,但它不会发生。再说一次,如何解决这个问题?

4

2 回答 2

7

得墨忒耳法则是关于依赖而不是 -> (或其他语言中的点)。

例如,如果您有一个流畅的接口(其中方法返回 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 字段的类。您还有更多可重用的代码。

于 2015-01-19T11:11:47.533 回答
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!

伙计,你是个电子迷,或者你是为了生活而做的——你知道你笔记本电脑的每一小块!;)

与这个:

You: Hey Laptop, I want to press left button on the touchpad
// Laptop gets the job done
Laptop: Done Boss!

在第二次谈话中,在引擎盖下,

  1. Laptop调用它的依赖项IODevices(你不需要知道任何关于它的信息),
  2. IODevices调用它的依赖KeyboardLatop不需要知道它),
  3. Keyboard得到它的依赖TouchpadIODevices不需要知道它 - 实际上这是一个有点糟糕的例子,但是......你明白了)然后调用pressLeftButton()它。

也就是说,你不关心细节,你想做的就是pressLeftButton。您不需要知道如何相关,Keyboard以及Touchpad每个方法返回的内容等。您拥有必须实现的公共接口。

这让每个人都高兴,因为当您替换为 时,只要后者实现相同的接口,什么都不会KeyboardXyz破坏KeyboardAbc

于 2015-01-19T11:37:04.077 回答