2009-07-27 47 views
3

假設我有一個門一個定義:OOD和主客混亂

class Door 
{ 
    public void Lock() 
    { 
     // lock the door 
    } 
} 

這似乎是有意義的我,至少一段時間。但現在,我不太確定。如果我有一個想要鎖門的Person對象,他會調用一個Door.Lock()。但在現實生活中,我們不會通過告訴門鎖自己來鎖門。

似乎更準確的情況模型是人能夠直接修改門的狀態,只要他有足夠的能力鎖門。例如,aCat不應該能夠設置aDoor.IsLocked = true。我可以看到如何與性能做到這一點,如果他們支持的參數:

class Person 
{ 
    public void LockDoor(Door door) 
    { 
     door.IsLocked(this) = true; 
    } 
} 

class Door 
{ 
    bool isLocked; 

    public bool IsLocked(Person person) 
    { 
     set 
     { 
      if(person != null) // ensure there is a real person trying to lock the door 
      { 
       this.isLocked = value; 
      } 
     } 
    } 
} 

static void Main() 
{ 
    Person personFromThinAir = new Person(); 
    Door doorFromThinAir = new Door(); 
    personFromThinAir.LockDoor(doorFromThinAir); 
} 

相反,我們所能做的就是:

class Person 
{ 
    public void LockDoor(Door door) 
    { 
     door.SetLocked(this, true); 
    } 
} 

class Door 
{ 
    bool isLocked; 

    public void SetLocked(Person person, bool locked) 
    { 
     if(person != null) 
     { 
      this.isLocked = locked; 
     } 
    } 
} 

顯然,這兩個類是強耦合,並且都可能會有在實際代碼中提取的接口,但這不是我所掌握的。我的問題是,這是模擬兩個對象之間關係的更好方法嗎?有沒有比這更好的方法?我對它的考慮越多,我可以做出的Do.O.Lock()的感覺就越少;它似乎違反了面向對象的設計。

回答

9

雖然人「鎖定」的大門,在現實中的人被觸發(或frobbing)在門的一個元件上(鎖手柄),並且該操作導致鎖將門鎖定。你可以想到這個地方,雖然這個人正在移動死角,但是死鎖是鎖門的東西 - 而不是人。所以一個更好的表示可能是一個門有一個鎖,而這個人調用lock.lock(),然後設置鎖被關閉(鎖定)。

這裏的基本前提是,雖然人在操縱鎖,那是外部的(函數調用)。鎖的內部變化(函數內部的代碼)實際上是導致門鎖定的原因。人不會每次都脫下手柄並操縱內部鎖門 - 他們只是簡單地在外面打開一個狀態,期待內部機器處理它。

+0

好說 - 打字比我快! – 2009-07-27 16:27:30

6

面向對象並不是真正關於如何在「現實世界」中工作的建模。其更多關於管理複雜性。考慮到這一點,門自鎖是完全可以接受的。即使在現實世界中,除了轉動旋鈕或鑰匙之外,鎖定門的人不需要知道鎖的工作方式。

隱藏在抽象背後的複雜想法的細節是什麼使OOP如此有用。您使用的抽象與問題域不同。在這個例子中你給了人不應該需要了解的門什麼比如何操作其他:

class Door 
{ 
    public bool Open(){} 
    public bool Close(){} 
    public void Lock(){} 
    public void Unlock(){} 
} 
0

這裏最讓我感興趣的設計問題是如何處理鎖櫃和鎖定裝置之間的耦合,因爲鎖定/解鎖需要滿足一定的要求。我看着這個問題,想象一個遊戲,玩家有時可能是一個人,但其他時間是一隻貓(根據給出的例子),也許is_human是鎖定/解鎖的唯一要求。但是,您也可能希望有門需要匹配鍵才能進入玩家的位置,以便鎖定/解鎖。如果是這樣,你必須添加到標準。也許有些門只能從一側鎖定,而不能從另一側鎖定,所以玩家的位置必須添加到標準中。你可以進一步增加一些玩家可能擁有的開鎖技能(無疑是貓鼬竊賊),讓他們有機會解鎖(但不鎖)門,即使他們沒有鑰匙。等等

人們可以像想象中的對象之間的對話:

Player: "I am trying to unlock you." 
Lock: "Do you meet requirement A?" 
Player: "Yes" 
Lock: "Do you meet requirement B?" // Only some doors would ask this. 
Player: "Yes" 
Lock: "OK, you succeed. I am unlocked!" 

但是,你可能不希望公開揭露所涉及的領域或弄亂由不需要的對象看到的播放器界面瞭解鎖定/解鎖要求。

我不是C#程序員,從我做Java開始就已經有一段時間了,但我認爲Java中的一種方法可能也適用於C#,它將讓Player對象通過一個lock_unlock_credentials內部類的實例作爲門對象的方法的參數(或者已經建議的鎖對象).對象將具有回調方法,由於其作爲玩家的內部類,可以訪問玩家的相關字段對象,但這些字段否則不會暴露在玩家之外。 Lockable對象然後可以使用這些回調方法來檢查它所關心的需求是否被滿足。您無法避免由需求產生的耦合,但這種方式保持了Player和Lockable對象之間交互的內部細節。

不知道是否相同的內部類的方法適用於C#,但提出這是一些思考。