2010-01-23 69 views
5

假設您有一個名爲Explosion的類,在創建它的實例時沒有意義,而沒有來自另一個類實例的某些信息。構造函數不公開。根據Java中另一個對象的狀態創建一個對象

是更好地做這種方式:

// both classes are in the same package 
Explosion e; 
Collision c = new Collision()  
// do some stuff with collision 
e = c.createExplosion() 

或者是爆炸最好有一個靜態方法來創建一個實例,你在一個碰撞對象作爲參數傳遞:

Explosion e 
Collision c = new Collision()  
// do some stuff with collision 
e = Explosion.createExplosion(c) 

當你是這兩個類的作者。

+0

當我爲簡單的單元測試進行設計時,我最終選擇了最喜歡的解決方案。靜態方法和'新'運算符指出特定的類並使模擬實現變得困難。 – Christian 2010-01-23 16:20:31

回答

1

我當然更喜歡第二個,因爲那是OO。

4

爲什麼構造函數不公開? Explosion有一個構造函數,它將Collision引用作爲參數對我來說似乎是明智的。

這樣,你可以有:

Explosion e; 
Collision c = new Collision(); 
// do some stuff with collision 
e = new Explosion(c); 
3

我傾向於第二種方法,因爲它更好地劃分階級之間的責任。要回答你的問題,問問你自己誰有責任創建一個爆炸,並採取相應的行動。你的第二種方法基本上使用工廠方法來隱藏構造函數,但責任仍然在爆炸類中,這是良好的IMO。

爲什麼構造函數不公開?你可以使它包裝可見,然後通過碰撞作爲構造參數?

3

這主要取決於依賴性。

如果您認爲Explosion始終是較低級別的或Collision的同級,那麼請考慮靈活性和易用性(虛擬)實例方法。這保持了對象的行爲,並減少了對getter的需求(這往往是設計不佳的標誌)。當然,您仍然可以撥打Explosion的構造函數,但現在只有Collision

另一方面,如果Collision不應該依賴Explosion,那麼直接使用構造函數。這不是虛擬方法的結束。如果事情變得更加複雜,您可能會更改調用代碼,以在其他某個對象上調用虛擬方法,該對象會從傳入的Collision中創建Explosion的特定配置。

1

這真的取決於您的系統的範圍。 如果你真的想要「完整的延伸」,這應該由第三類來處理,代表系統中的交互的「物理」。

這是爲什麼: 首先,碰撞會產生很多後果:爆炸,傷害,得分(這是一場比賽)?聲音等等。你不想將它們全部放入碰撞中。另一方面,爆炸可能由於許多不同的原因而發生(例如武器),爆炸是否應該明確地知道可引起爆炸的所有因素?

如果你正在模擬「世界」的許多方面,你可能想要第三個系統負責這些因果關係。它需要它所需要的一個對象的狀態,並創建另一個具有必要的狀態而不必彼此瞭解的對象。

1
  • Effective Java (2nd chapter)建議使用靜態工廠方法,即您的第二個選項。
  • 根據從Collision您在爆炸所需要的參數,它可能是更好的傳遞只有那些參數,因此不會違反與第二種方法的Law of Demeter
1

一個優點是你不需要創建防爆對象每次(參考Effective Java)。 如果你想擁有某種緩存機制(比如說你想基於類Collision的某些屬性返回一個相同的爆炸實例),那麼第二種方法是有幫助的。

另一方面,如果Explosion類僅爲實例創建提供靜態工廠方法,則不能進行子類化。

相關問題