2017-10-07 55 views
4

一個很簡單的一點:這也違反了德米特法則?或者這會扭曲它的矯枉過正?

class Point 
{ 
    private $x, $y; 

    public function __constructor($x, $y) 
    { 
     $this->x = $x; 
     $this->y = $y; 
    } 

    public function getX() 
    { 
     return $this->x; 
    } 

    public function getY() 
    { 
     return $this->y; 
    } 
} 

和一個圓

class Circle 
{ 
    private $r; 
    private $point; 

    public function __constructor (Point $point, $r) 
    { 
     $this->point = $point; 
     $this->r = $r; 
    } 

    public function getPoint() // here is the law breaking 
    { 
     return $this->point; 
    } 
} 

$circle = new Circle(new Point(1,2), 10); 
$circle->getPoint()->getX(); // here is the law breaking 
$circle->getPoint()->getY(); // here is the law breaking 
當然

它打破了迪米特法則。因此,讓我折射它:

class Circle 
{ 
    private $r; 
    private $point; 

    public function __constructor (Point $point, $r) 
    { 
     $this->point = $point; 
     $this->r = $r; 
    } 

    public function getPointX() 
    { 
     return $this->point->getX(); 
    } 

    public function getPointY() 
    { 
     return $this->point->getY(); 
    } 
} 

$circle = new Circle(new Point(1,2), 10); 
$circle->getPointX(); 
$circle->getPointY(); 

除了它看起來更好,我沒有看到任何好處 - 只是兩個額外的包裝功能部件。從技術上講,我再次可以完全訪問Point,並且沒有辦法將更多方法添加到Point。是否仍然值得使用第二折射方法?

+1

如果您將Point更改爲3D點,您現在必須更改使用Point的每個類?這似乎是一個向後移動 - 恕我直言。 –

+1

@NigelRen將2D點改變爲3D點使得繼電器沒有意義恕我直言。如果他需要3D點,他可以通過'class Point3D extends Point'從2D點繼承一個3D點。 – Webdesigner

+1

即使您確實定義了一個子類,在第二個設計中該如何照顧?至於從二維到三維的點 - 當然,整個觀點是你不在乎點是什麼 - 我應該能夠改變它到15D點,第一個設計工作,第二個設計失敗! –

回答

1

旁事實,這更多的是基於觀點的問題,我會做這樣的:

class Circle extends Point 
{ 
    private $r; 

    public function __constructor (Point $point, $r) 
    { 
     $this->x = $point->getPointX(); 
     $this->y = $point->getPointY(); 
     $this->r = $r; 
    } 
} 

$circle = new Circle(new Point(1,2), 10); 
$circle->getPointX(); 
$circle->getPointY(); 
1

我同意@Webdesigner,這是相當的意見基礎問題。

但是,在我看來,我認爲當你考慮Point是一個value object時,我不認爲違反demeter的法律是一個真正的問題。

吸氣可能是

public function center() : Point { ... }; 

,使之顯得更加清晰。

+0

我會爭辯說,僅僅因爲你指定了標籤「價值對象」,這並不免除遵循良好設計實踐的對象。德米特法也適用於價值對象,因爲它適用於每個對象。 –

+0

@RobertBräutigam:考慮到你在答案中提到的文章,價值對象本身不是問題。它可以有一個方法distanceToPoint(Point),它可以「做一些有用的事情」。圓會需要相同的方法來計算到一個點或另一個圓的距離,而不是使中心點可用。這是我在討論您的文章時分享的關注點。能夠通過一個Point來提供有用的方法,而不是X和Y的容器,最終對我來說很有用。 – Stefan

1

雖然第二個版本在技術上並沒有違反德米特法,但我認爲它仍然「違背了精神」。你不能說出哪一個更好的原因是因爲第二個在信息隱藏和封裝(Demeter法試圖編纂的東西)方面比第一個稍好一些。該法是關於隱藏對象的內部結構,從而實現封裝,信息隱藏和防止耦合。吸氣者(訪問者)本身就是信息隱藏的對立面,他們可以訪問內部結構而不是阻止它。

總結:吸氣劑是你的問題。只要你有這些,你將永遠不得不打敗德米特法,而你可能會失敗:)

好的,那麼你如何在沒有getters的情況下編碼?那麼,你添加的方法東西給你的座標。你需要的東西。點之間的距離,轉換點等等。無論您在當前應用程序中需要什麼。考慮一下在您當前的上下文中,什麼意思是

查看「The Genius of the Law of Demeter」。

+0

優秀的文章。特別是在討論中的前幾個職位。感謝分享。 – Stefan

相關問題