2016-04-20 71 views
2
interface DoSomething 
{ 
    public function do(); 
    public function getId(); 
} 

class DoSomethingGood implements DoSomething 
{ 
    private $dependency; 

    private $id; 

    public function __construct($id, $dependency) 
    { 
     $this->dependency = $dependency; 
     $this->id = $id; 
    } 

    public function do() 
    { 
     if ($this->dependency->isActive()) { 
      return true; 
     } 

     return false; 
    } 

    public function getId() 
    { 
     return $this->id; 
    } 
} 

class DoSomethingBad implements DoSomething 
{ 
    private $id; 

    public function __construct($id) 
    { 
     $this->id = $id; 
    } 

    public function do() 
    { 
     return false; 
    } 

    public function getId() { 
     return $this->id; 
    } 
} 

我應該在這裏使用組合或繼承會更好嗎?區別在於這些類如何實現do()方法。第一類具有它所需要的依賴性和一些內部邏輯來決定,而另一類更簡單。組成或繼承

回答

1

我想你應該從概念上思考這個代碼。這些類之間的關係是什麼?是否is-a relationship or has-a relationship?

如果你可以說DoSomethingGoodDoSomething,那麼繼承反映得很好。您可以讓繼承者替換繼承的類和適當的多態。其他應用程序在選擇時會流暢運行,因爲它反映了您對此的看法。

如果你可以說DoSomething有一個DoSomethingGood那麼你應該使用組合。特別是如果你可以有很多DoSomethingGood。再次,如果這在概念上是正確的,那麼其餘的代碼很容易編寫。

有時看起來你可以對兩者都說「是」,線條模糊,但你應該在概念層面而不是在代碼層面考慮它。特別是如果你想了解模式,而不僅僅是「代碼重用」,這是一種關於繼承的微妙推理方式。

當你的選擇錯誤時,編碼將變得笨拙,違反直覺,不必要地複雜或不可能(矛盾)。如果發生這種情況,請回到製圖板並重新考慮您的選擇。

這就是說,你幾乎是唯一可以說出你想要什麼以及想做什麼的人。如果你使用DoSomethingGood這樣的名字,它是不明確的。

當你說Cat,DogAnimal時,它會容易得多。這裏很容易說出使用什麼(斷言「CatAnimal」是直覺上正確的)。

2

繼承是一種語義關係。不是組成。一個常見的錯誤是通過使用繼承而不是組合來分解代碼。

只看到Liskov substitution principle

+0

驚人的洞察力,請把一些鏈接到書,你在你的個人喜歡的文章,我真的不知道有什麼可以做一個這樣想。 – Arjang

+1

@Arjang看看面向對象設計的基本原則:[SOLID](https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)) – pid