Unity 游戲框架搭建 (二) 單例的模板

上一篇文章中說到的manager of managers,其中每個manager都是單例的實現,當然也可以使用靜態類實現,但是相比于靜態類的實現,單例的實現更為通用,可以適用大多數情況。

如何設計這個單例的模板?

先分析下需求,當設計一個manager時候,我們希望整個程序只有一個該manager對象實例,一般馬上能想到的實現是這樣的:

publicclassXXXManager {

privatestaticXXXManager instance =null;

privateXXXManager {

// to do ...

}

publicstaticXXXManager() {

if(instance ==null)

{

instance =newXXXManager();

}

returninstance;

}

}

如果一個游戲需要10個各種各樣的manager,那么以上這些代碼要復制粘貼好多遍。重復的代碼太多!!!想要把重復的代碼抽離出來,怎么辦?答案是引入泛型。實現如下:

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Text;

usingSystem.Reflection;

namespaceQFramework {

publicabstractclassQSingleton where T : QSingleton

{

protectedstaticT instance =null;

protectedQSingleton()

{

}

publicstaticT Instance()

{

if(instance ==null)

{

// 如何new 一個T???

}

returninstance;

}

}

}

為了可以被繼承,靜態實例和構造方法都使用protect修飾符。以上的問題很顯而易見,那就是不能new一個泛型(3月9日補充:并不是不能new一個泛型,參考:[new一個泛型的實例,編譯失敗了,為什么?-CSDN論壇-CSDN.NET-中國最大的IT技術社區](http://bbs.csdn.net/topics/390911693)),(4月5日補充:有同學說可以new一個泛型的實例,不過要求改泛型提供了public的構造函數,好吧,這里不用new的原因是,無法顯示調用private的構造函數)。因為泛型本身不是一個類型,那該怎么辦呢?答案是使用反射。實現如下:

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Text;

usingSystem.Reflection;

///

/// 1.泛型

/// 2.反射

/// 3.抽象類

/// 4.命名空間

///

namespaceQFramework {

publicabstractclassQSingleton where T : QSingleton

{

protectedstaticT instance =null;

protectedQSingleton()

{

}

publicstaticT Instance()

{

if(instance ==null)

{

// 先獲取所有非public的構造方法

ConstructorInfo[] ctors =typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);

// 從ctors中獲取無參的構造方法

ConstructorInfo ctor = Array.Find(ctors, c => c.GetParameters().Length == 0);

if(ctor ==null)

thrownewException("Non-public ctor() not found!");

// 調用構造方法

instance = ctor.Invoke(null)asT;

}

returninstance;

}

}

}

以上就是最終實現了。這個實現是在任何C#程序中都是通用的。其測試用例如下所示:

usingQFramework;

// 1.需要繼承QSingleton。

// 2.需要實現非public的構造方法。

publicclassXXXManager : QSingleton {

privateXXXManager() {

// to do ...

}

}

publicstaticvoidmain(string[] args)

{

XXXManager.Instance().xxxyyyzzz();

}

總結

這個單例的模板是平時用得比較順手的工具了,其實現是在其他的框架中發現的,拿來直接用了。反射的部分可能會耗一些性能,但是只會執行一次。在Unity中可能會需要繼承MonoBehaviour的單例,因為很多游戲可能會只創建一個GameObject,用來獲取MonoBehaviour的生命周期,這些內容會再下一講中介紹:)

附:[我的框架地址](https://github.com/liangxiegame/QFramework)

轉載請注明地址:[涼鞋的筆記](http://liangxiegame.com/)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容