close
Singleton是甚麼
遊戲實作中的唯一物件,地球是唯一的,太陽是唯一的...
放在遊戲世界裡,同時間只能有一個關卡進行,只能同時操作一個遊戲角色...
類似GM的存在
兩種特性
- 同時間只存在一個
- 提供快速取得這個物件的方法
可以這樣寫:
class StaticClass { public static StaticClass instance; public StaticClass() { instance = this; } }
雖然這樣能達到上面的兩個特性,但這潛在了被修改的風險
例如:
只要在其他Code上
StaticClass.instance = null;
或是
StaticClass.instance = new StaticClass();
都會直接把instance修改掉
Singleton解決方法:
class StaticClass{ public string name = "StaticClass"; private static StaticClass instance; public static StaticClass Instance{ get{ if(instance == null){ instance = new StaticClass(); } return instance; } } }
P.S.這邊順便提一下命名,通常靜態變數開頭為大寫,為了與一般變數做區隔,一般變數通常用小寫
如此這樣一來,就可以用一行程式碼就可以直接取得此物件,也不會被修改
print(StaticClass.Instance.name);
其實不是因為貪求方便性所有類別都用Singaton,有時候其實是可以避免的
在設計的時候可以想看看,要求的功能是上述兩個特性都要還是只要其中一個
如果只是要求同時間只存在一個 :
public class ClassWithCounter { static int m_ObjCounter = 0; bool m_bEnable = false; public ClassWithCounter() { m_ObjCounter++; m_bEnable = (m_ObjCounter == 1) ? true : false; if (m_bEnable == false) { Debug.LogError("目前物件數 : " + m_ObjCounter + "超過一個"); } } public void Operator() { if (m_bEnable == false) return; Debug.Log("可以執行"); } }
可以在別的類別下測試 :
public class Test : MonoBehaviour { public void Start() { ClassWithCounter cwc = new ClassWithCounter(); cwc.Operator(); ClassWithCounter cwc2 = new ClassWithCounter(); cwc2.Operator(); cwc.Operator(); } }
執行結果:
如果是要讓物件可以容易被取得,可以設定為類別的參考 :
public class ObjectTest { public ObjectTest(Test ob) { ob.GetMessage("用GetObject的方法"); } } public class Test : MonoBehaviour { public void Start() { ObjectTest objectTest = new ObjectTest(this); } public void GetMessage(string message) { Debug.Log(message); } }
單例模式濫用問題:
- 被引用的對象不能被GC回收。比如引用了資源對象,被Destroy後,雖然c++端的内存被釋放了,但是c#端的對象引用還存在。如果不小心引用了一個Component,Component又引用了一大堆其他Component,則引用鏈上的所有對象都將無法被GC回收。
- 耦合度變高。如果大量單例對象間交叉引用,會讓代碼變得很亂,不方便後續維護;而且工程如果大了以後,也不方便拆分工程,引起編譯時間過長。可以適當的拆分重组一下功能,讓引用盡量變成單向的。也可以引入事件中心,来解耦合。
- 功能安全性。成員變數容易被其他地方隨意修改,不好排查。某些方法可能是特定場合才使用的,但是其他人並不知道。
- 線程安全。涉及到線程相關的操作,非常容易出事。
文章標籤
全站熱搜
留言列表