2010-09-22 15 views
2

我想開始使用OOAD,這個問題出現在我的腦海裏,我不確定我能找到一個好的解決方案:(它是一個真實世界案例的超級簡化版本)。哪個是這個簡單的OOAD問題最優雅的設計?

漁夫用魚竿在池塘裏釣魚。 在釣魚線的每次發射時,當有陽光和晚上1/20時,捕捉魚的可能性等於1/10。

要定義哪些類? 我會回答:漁夫,釣魚杆,池塘,日(模擬日夜)。

哪些方法? 我會回答:Fisherman.Launch(釣竿),FIshingRod.TryToFish(池)返回布爾

如何的可能性模型?誰有可能性的責任?它不屬於漁民,也不屬於池塘。在這個例子中,只與日光有關係,在現實世界中它也可能與漁夫,釣魚竿和池塘有關。

如何建模外部因素(日光)?

歡迎任何評論。還編碼示例。

UPDATE: 的問題和tdammers的第一評論回答逼我更加具體。 正如我在上面寫到的「它是一個真實世界案例的超級簡化版本」,無論如何,假設我想在以後增加複雜性,而不是超級增加它,讓我們說增加它足夠好,以便讓所有的類(例如,因爲我記錄了池塘裏有多少魚,漁夫有多累,......)。無論如何,對我來說最有趣的問題是「如何模擬可能性」和「外部因素」。 將此視爲對OOAD中技能不熟悉的人的新手問題。

+2

「最優雅的設計」在很大程度上取決於您的釣魚領域類庫的典型用戶想要做什麼。他們正在製作釣魚電子遊戲嗎?大規模蒙特卡洛模擬與許多模擬試驗研究孵化場枯竭?一個設計可能完全適合於一個用例,但它過於複雜,不適合甚至無法用於其他用例。有些設計對於任何用例都是不利的,但是很難說設計是優雅的而不考慮預期的用途。 – 2010-09-22 21:39:09

+0

好吧,非常好的一點。讓我更新我的問題,以便我可以縮小可能的答案。 – LaBracca 2010-09-22 21:46:56

回答

7

我會有漁夫,釣魚杆,釣魚線,池塘,魚和「天空」(或「環境」)。

在面向對象的土地上,對象通常最終會比你想象的更聰明。漁夫「有一個」(含有)FishingRod。他將FishingLine(FishingRod的一個組成部分)投射到池塘中。池子「看着」天空以確定它是白天還是晚上,然後擲骰子以確定是否應該放魚。

搖出的對象層次結構是一個FishingLine可以有選擇地包含一個Fish,並由一個漁夫擁有的FishingRod擁有。該池塘包含魚,接收FishingLines但不「擁有」他們,也知道但不擁有天空。

方法後面將像以下:

Fisherman.FishingRod - 初始化屬性(或對getter/setter方法)中使用,得到漁夫一個釣竿到FishAt()與池塘。這是可選的;一個漁夫可以創建他自己的釣魚棒,或者他自己可以從一堆釣魚棒中選擇它,而不是給他釣魚棒。 Fisherman.FishAt(Pond) - 告訴漁夫用他的FishingRod將FishingLine發射到池塘中,然後檢索它可能會得到一條魚。

FishingRod.Launch(Pond) - 將FishingRod的FishingLine放入池中。

FishingRod.Retrieve() - 從池中檢索FishingLine,返回一個Fish,這也可能不是什麼。

Pond.StockWith(Fish []) - 爲漁民提供池魚以捕獲釣魚杆。請記住,在OO土地上,所有東西都要麼被賦予它想要的東西,要麼知道如何去做;如果這是你想要遵循的模型,那麼池塘可以很容易地創建魚,但是這裏的用戶故事並沒有說明這是怎麼發生的(通常意味着它超出了故事的範圍)。

Pond.SetFishingLine(FishingLine) - 由FishingRod用於將其FishingLine放入池中。這是合併業務邏輯的「驅動功能」。當這個被調用的時候,池塘應該詢問天空是否是白天,並且可能根據一天中的時間將魚放在釣魚線上。

Sky.IsDay() - 一種方法,如果是白天則返回true,如果是晚上則返回false。

如果您認爲池塘不應該直接知道魚被放在FishingLine上的具體規則,它可以將FishingLine和它的魚[]稱爲「純粹製造」。這種製造「漁業邏輯」將是審查天空並應用規則的人。在開發過程中,這通常是一件好事,因爲這意味着FishingLogic可以在不改變Pond的情況下進行更改,除非FishingLogic需要更多來自Pond(如水溫)。

的各種對象表示各種基本的「模式」在現實生活中的編程:

  • 漁夫是一個「演員」,最接近的模擬我們的用戶。像這樣的系統的用戶基本上站在演員的肩膀上,告訴他該做什麼。
  • FishingRod是一個「幫手」或「實用工具」。它是「工具」的真實世界模擬,並且包含狀態和業務邏輯的混合,幫助它執行非常具體的任務。
  • 此模型中的FishingLine類似於「請求」或「命令」。它的唯一目的是從一個對象到另一個對象,當這種情況發生時,它表示接收者應該採取特定的行動。
  • 魚是一種「反應」;對請求的回答。可能有一個,也許不是。
  • 池是一個「存儲庫」;它包含了一些東西,並根據一組邏輯處理外部對象對這些東西的請求。
  • 天空是一個「國家桶」。它有數據,並通過其接口提供對數據的訪問。
  • FishingLogic是一個「純粹的製造」;它與我們正在建模的現實世界中的「名詞」(對象)沒有任何相似之處,它的存在是爲了包含環境規則,或者是在沒有模型對象必須知道的情況下發生的事情(魚如何決定如何掛鉤?)
+0

非常感謝,這正是我所尋找的答案。關於FishingLogic的討論非常有趣。 Basiaclly所有在現實世界中所不具備的東西(一個池塘不問天空)可以(這不是強制性的,當然,這取決於場景的複雜程度)被授予「純粹製造」。當我(我希望)在現實世界中使用OOAD時,我會保留這個答案並在幾個月內再次審查它。謝謝。 – LaBracca 2010-09-22 22:39:07

+0

非常好的答案!只有一個問題:爲什麼池塘會決定是否放魚?魚本身不能看着天空,決定去吃點東西嗎?然後,你最終也可以有一條魚的「飢餓」,「咬幸福」,「攻擊性」等決定是否有任何魚或更多的魚決定在鉤上運行。 – 2010-09-23 06:28:20

+0

@Marjan和Keith:可以這樣說,直到模型沒有魚類,一個類必須負責什麼事實上是一個魚決定(不管是不是掛鉤),在這種情況下,FishingLogic類是有意義的嗎?當然,如果一個人開始模擬魚類,池塘變得與現實生活中的相似:它不是水和魚的混合物,而只是魚類的混合物。因此,如果我認爲,一個域中的類與「真實世界」的複雜性相匹配的程度越高,那麼對象的行爲就會與現實世界中的「完全相同」。 – LaBracca 2010-09-23 07:15:49

2

沒有課。沒有方法。一個有三個參數的函數。

bool launch_rod(bool daytime, float chance_daytime, float chance_night) { 
    float chance = daytime ? chance_daytime : chance_night; 
    float cast = random_float(); 
    return cast < chance; 
} 

這就是它的全部。 也許,也許,將整個事物包裝在一個類中,並且創建該類的chance_daytime和chance_night屬性。鑑於規格,其他任何東西都是過度工程。

+0

Lol :) OP說:「這是一個真實世界案例的超級簡化版本」。所以當然這是過度設計的。問題依然存在。 – 2010-09-22 21:43:09

+3

這是一個OOA&D問題。他們想要的答案根據定義將是一個過度工程化的答案。 – KeithS 2010-09-22 21:45:08

2

魚類也可以「看天空」來決定它有多餓。 池塘類似乎相當惰性。

Fisherman, Rod, Line, Fish, Sky 

Fisherman.cast(), .drinkBeer(), .chooseRod(), .addLineToRod() 
Rod.cast() 
Line.cast() 
Fish.bite() 
Fish.checkDay() 
Sky.isDay() 
相關問題