2011-12-21 59 views
3

對於特定的OOP問題的組織,我有一個快速的問題。OOP組織問題的最佳解決方案

說我有一個地形類,充滿了瓷磚。類Tile有多個衍生物,即Door。門類有一個叫做open()的方法,它打開門,close()關閉門。這是非常有意義的,直到這兩種方法在打開和/或關閉之前都需要檢查某些東西。如何在不知道其父項的情況下對某個對象進行門檢查?

一個簡單的解決方案是在調用open()之前檢查某些東西,但是如果有不同類型的門需要檢查不同的形狀,它會在更高的層次上造成混亂。

看起來這會有一個簡單的答案,但它似乎也經常遇到這個問題,往往不是。

+3

門是不活動的,一個處理程序打開並關閉它們,正是這個處理程序需要檢查門是否被鎖定/鎖定/已經處於它想要的狀態。門只知道自己,而不瞭解其環境中的其他事物。 – slashmais

+0

@slashmais所以我的解決方案是正確的? – lowq

+0

是的,看起來很正確 - 不同的處理程序每​​個人在接近門的方式上都有不同的能力;例如:你會解鎖並打開你的房門,警察會踢它,一個自動化的設備將它做的事情等。 – slashmais

回答

2

一個答案是,門應該知道如何打開和關閉自己,並知道他們是否被阻止。如果門是一類,那麼這兩個國家( IS_OPEN is_blocked)和行爲( open_the_door close_the_door)應駐留在門類。封裝是面向對象範例的基本原則。

但是現實世界的答案通常比較微妙。你能提供一些有關應用程序的背景知識以及它需要完成什麼?有一些乾淨簡單的解決方案可以很好地適用於玩具應用,但是更大的應用需要更復雜的東西。

如何處理門 is_blocked提出了一些設計問題。沒有一個正確的設計,但有好的設計和糟糕的設計。將好想法與壞想法區分開不僅僅取決於設計原則 - 它取決於問題的背景。如果我不得不猜測,我猜你的應用程序是一個遊戲。也許瓷磚代表遊戲板或地圖的區域。您已經發現許多不同的對象可能需要互動,並且如果它們都直接互相引用,它們將會混亂。

  • 遊戲通常會有一個名爲「Game」或「Board」或「Map」的主對象。讓主對象保存Tile層次結構中的事物(瓷磚,門等)的集合。

  • 讓主對象也容納可阻擋門或以其他方式與瓷磚和門交互的東西的集合。

  • 現在在接受對象作爲參數的Tile類上創建一個名爲update()的方法。

  • 然後爲Door類創建一個名爲「blocked」的布爾屬性。 Door的更新方法可能會這樣:

    Door::update(BlockingObject object) { 
    if(object.location == this.location) 
         blocked = true 
    }

  • The method on the superclass of door might do nothing. Like this:

    Tile::update(BlockingObject obj) { 
        //tiles cannot be blocked 
    }

  • Now, inside the game loop, include a step where all the doors are set to blocked = false

  • 創建一些循環會要求所有圖塊檢查它們是否被阻塞。它看起來在僞代碼是這樣的:

    For each tile { 
        For each blocking object { 
          tile.update(object) 
        } 
    }

  • 這是一個天真,但直截了當的設計,成立於二OO範例。

  • 該設計爲瓷磚/門和物品提供了一次回合互動一次的機會,而不會強迫他們彼此引用。

  • 該設計對於幾百個瓷磚和物體可以正常工作,但對於數千個瓷磚來說,它會變得非常緩慢。

這是一個很好的設計嗎?

答案取決於應用程序的需求。

+0

是的。這絕對是一場遊戲。我喜歡你的解決方案,但'update(BlockingObject)'看起來像一個函數,它只駐留在一扇門上,不應該應用到其他瓷磚上。 我還可以看到只有在添加或刪除磁貼時才更新周圍磁貼。 – lowq