Re: [程式] Unity的Singleton Pattern實作-Instance
先感謝分享,但這邊提出一些不同的看法。
Singleton 本身並不會降低耦合,實際上它造成很強烈的耦合。
我們可以參考一下耦合的定義
https://en.wikipedia.org/wiki/Coupling_(computer_programming)
Singleton 本身就是個 global state,因此它造成了 common coupling
任何使用到這個 singleton instance 的物件,彼此會造成影響。
它其實就是全域變數。所有教科書上列舉的全域變數缺點,在 singleton
身上都適用,比如說:
1. 人人可用的物件,代表人人可破壞。一旦這個物件的內容出現錯誤,
要找到發生問題的地方會變得比較困難。
想像 S 是 singleton,A 與 B 是兩個不相關,但都使用到 S 的物件,
有可能 A 的錯誤導致 S 的內容錯誤,而 S 的錯誤又導致 B 的錯誤。
這類高耦合下的錯誤會讓你花很多時間在追查錯誤根源。
2. 程式碼的擴充變得困難。想像一下原本是個單人遊戲,因此你為了方便
使用 singleton 來實作 player,結果過一陣子後企畫決定把玩法改成
雙人合作,singleton 會讓你的程式架構改得非常辛苦。
3. 碰到 multi-threading 相當麻煩,如果你對每個 singleton method
都增加 lock,效能會變得很差。
4. 難以使用 mock object,因此也難以自動化測試。
而大部份 singleton 想達成的目的,都有別的方法可以做到。比如說
* 想要在很多地方用到同一個物件,你傳參數就好。
* 許多物件重覆被傳來傳去很麻煩,你可以收集起來做成一個 context object。
* 不希望某個物件被產生兩次,你可以把建構式標為 internal,
然後在另一個地方產生好餵進 context object。
* 想做到 lazy initialization,你可以自訂 context object 的 getter。
誠然,有些地方 singleton 沒有那麼槽,比如說提供一個寫 log 的服務。
因為寫 log 只是單向輸出,不會影響其它物件,玩家可能也看不到 log。
但是,因為 GoF 的 design pattern 根本沒討論這些問題,
加上它有個 pattern 讓許多初學者覺得「用了一定比沒用好」
大部份的情況,singleton 就是被濫用的。Unity 就是最好的例子,
在 Unity 中要使用 multi-threading 或是做測試,都變得困難重重。
其它參考資料:
* Game Programming Patterns
http://gameprogrammingpatterns.com/singleton.html
* Why Singletons are Evil
https://goo.gl/qN59Ud
* Use your singleton wisely
https://goo.gl/vi9aQM
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 125.227.5.133
※ 文章網址: https://www.ptt.cc/bbs/GameDesign/M.1505060613.A.66F.html
留言