一個OOAD的設計問題(轉帖+理解)

原文地址:http://www.cnblogs.com/bluedoctor/archive/2011/06/01/2067177.html#pagedcomment

   在RPG遊戲中,人物攜帶物品在地圖中走動,不同的物品具有不同的功能,如果就這麼簡單,那對物品的使用,就可以成爲物品的一個方法,使用物品就調用這個方法好了。

    很要命,不同的人物使用同一件物品的時候,效果也不一樣。

    這時候還要把這個方法放到物品對象中嗎?

    也許還可以,OO分析會開始非人類的胡言亂語:如果在方法調用中,加上user參數,那麼物品知道是誰在使用它,於是就可以根據使用者的不同來進行不同的處理了。

    賣鍋的,物品居然活了,它成了一個精靈,知道誰在使用它。

    好吧,這樣是可以了。但問題是,做爲一件物品,它爲了根據使用者的不同來進行不同的處理,那麼它就得知道使用者的類型,耦合就產生了,即使你又抽象出某種公共的接口,耦合依然存在,但處理上會稍微舒服一些。

    有人試圖改變這種耦合,把使用物品的方法加到了人物對象上,只不過是顧頭不顧腚的做法,按下葫蘆浮起瓢。這裏的耦合不見了,會在另外一個地方冒出來,只不過,有經驗的設計者會預先知道這一點並權衡不同方式的利弊,對於性質不同的系統,採用不同的處理方式。

    如果再加上一種,那就是場景,比如地上打和地下使用不一樣,在莊稼地和宮殿裏使用也不一樣,那又該如何?

    請園子裏面的大牛,告訴我這個問題該如何OOAD?

 

下面是我和作者的一些評論:

 

#22樓2011-06-02 13:57zylcf818      

head first設計模式開頭的那個例子(關於鴨子及其行爲的)和你這個有相似性。先看一下那個例子,再看我下面的內容會更好理解。
我的一些初步看法是user和物品都設計成接口,這樣就把具體物品和具體user間的耦合解耦了。
user本身聚合有很多物品,在使用的時候只調用物品的use方法就行了,這裏有幾點說明:
1 在調用的時候,user和環境對象(也就是各種影響動作執行的因素數據)作爲參數傳入use方法中,這裏羅嗦2句:除非特殊原因,一定要用參數傳入,不要讓物品從其他途徑獲得,原因大家應該明白;
2 具體的物品對象的use方法內部如何處理,看你了,邏輯簡單用if else判斷各種影響因素後執行那個動作,如果邏輯複雜,還是要在分析,這裏又要羅嗦2句,對於不同情況,千萬不要用繼承的方式去對應各種case,這樣會造成類爆炸,應該使用對象組合將動作再分解爲小對象後組合到具體的物品對象裏。
3 user通過系統獲得物品,user可以有一個receive接口,其參數是物品接口,系統通過user的receive方法給user增加一個物品,user不用關心該物品的具體類型
舉個例子:
角色和武器之間的關係,武器的使用受到角色(如精靈,矮人等),環境(空中,地上,沼澤)和角色等級等因素的影響。用2個接口表示角色和武器:IRole and IWeapon,
interface for IRole:
...
void add(IStuff aStuff)// IWeapon is subclass IStuff,個人覺得不要用addWeapon接口,這樣的接口設計很僵硬

interface for IWeapon:
...
void attack(IRole owner, IEnviroment aen, IRole aenemy)// use應該是IStuff的接口,attack是IWeapon的接口;

 

#24樓[樓主]2011-06-02 18:39深藍醫生      
@zylcf818
2 具體的物品對象的use方法內部如何處理,看你了,邏輯簡單用if else判斷各種影響因素後執行那個動作,如果邏輯複雜,還是要在分析,這裏又要羅嗦2句,對於不同情況,千萬不要用繼承的方式去對應各種case,這樣會造成類爆炸,應該使用對象組合將動作再分解爲小對象後組合到具體的物品對象裏。
---------------
看來這個物品對象還是一個“精靈”啊,它要根據傳進來的user接口具有的屬性,如角色,等級等,在結合環境因素,來最終決定自己該如何use.
也許你的方案可行,但會有一堆的if else,或者一堆對象的組合,怎麼做我都覺得,方案具體實施還是太複雜。

#25樓2011-06-04 15:00zylcf818      
@深藍醫生
怎麼做我都覺得,方案具體實施還是太複雜。
代碼的邏輯必然要反映業務的邏輯,如果你的業務邏輯簡單,代碼邏輯自然也簡單,這是規律。
看來這個物品對象還是一個“精靈”啊
在做OOAD時,考慮的是對象的職責以及怎樣隔離變化,UI上的表現和底層的對象不可能都有直接必然的映射和關聯。

沒有方案一開始就是複雜的,最開始的方案都是簡單的,複雜是由於各種需求和其他因素逐步進化造成的,你也可以看看另一個例子:《重構-改善既有代碼的設計》裏面開頭用的一個簡單例子,關於電影租賃系統的,演示了隨着需求的變化,而使系統逐漸複雜起來的過程。

#26樓[樓主]2011-06-04 16:59深藍醫生      
@zylcf818
謝謝兄弟的回覆,看來複雜性無法避免,我想的是,這類複雜的問題,能否找到OOAD之外的方法。實際上本文的問題不是我提出來的,而是另外一個朋友在博客中的討論,他提出可以使用Prolog的Horn字句來解決這類問題,也就是“陳訴式”的編程方式,採用語言內置的推理機來解決問題。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章