哈嘍,歡迎來到匯寶盆,首先非常感謝作者涼鞋的筆記分享這篇文章,上一篇文章中說到的manager of managers,其中每個(gè)manager都是單例的實(shí)現(xiàn),當(dāng)然也可以使用靜態(tài)類實(shí)現(xiàn),但是相比于靜態(tài)類的實(shí)現(xiàn),單例的實(shí)現(xiàn)更為通用,可以適用大多數(shù)情況。 如何設(shè)計(jì)這個(gè)單例的模板? ??先分析下需求,當(dāng)設(shè)計(jì)一個(gè)manager時(shí)候,我們希望整個(gè)程序只有一個(gè)該manager對(duì)象實(shí)例,一般馬上能想到的實(shí)現(xiàn)是這樣的: public class XXXManager { private static XXXManager instance = null; private XXXManager { // to do ... } public static XXXManager() { if (instance == null) { instance = new XXXManager(); } return instance; } } ??如果一個(gè)游戲需要10個(gè)各種各樣的manager,那么以上這些代碼要復(fù)制粘貼好多遍。重復(fù)的代碼太多!!!想要把重復(fù)的代碼抽離出來,怎么辦?答案是引入泛型。實(shí)現(xiàn)如下: using System; using System.Collections.Generic; using System.Text; using System.Reflection; namespace QFramework { public abstract class QSingleton<T> where T : QSingleton<T> { protected static T instance = null; protected QSingleton() { } public static T Instance() { if (instance == null) { // 如何new 一個(gè)T??? } return instance; } } } ??為了可以被繼承,靜態(tài)實(shí)例和構(gòu)造方法都使用protect修飾符。以上的問題很顯而易見,那就是不能new一個(gè)泛型(3月9日補(bǔ)充:并不是不能new一個(gè)泛型,參考:new一個(gè)泛型的實(shí)例,編譯失敗了,為什么?-CSDN論壇-CSDN.NET-中國(guó)最大的IT技術(shù)社區(qū)),(4月5日補(bǔ)充:有同學(xué)說可以new一個(gè)泛型的實(shí)例,不過要求改泛型提供了public的構(gòu)造函數(shù),好吧,這里不用new的原因是,無法顯示調(diào)用private的構(gòu)造函數(shù))。因?yàn)榉盒捅旧聿皇且粋€(gè)類型,那該怎么辦呢?答案是使用反射。實(shí)現(xiàn)如下: using System; using System.Collections.Generic; using System.Text; using System.Reflection; /// <summary> /// 1.泛型 /// 2.反射 /// 3.抽象類 /// 4.命名空間 /// </summary> namespace QFramework { public abstract class QSingleton<T> where T : QSingleton<T> { protected static T instance = null; protected QSingleton() { } public static T Instance() { if (instance == null) { // 先獲取所有非public的構(gòu)造方法 ConstructorInfo[] ctors = typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic); // 從ctors中獲取無參的構(gòu)造方法 ConstructorInfo ctor = Array.Find(ctors, c => c.GetParameters().Length == 0); if (ctor == null) throw new Exception("Non-public ctor() not found!"); // 調(diào)用構(gòu)造方法 instance = ctor.Invoke(null) as T; } return instance; } } } 以上就是最終實(shí)現(xiàn)了。這個(gè)實(shí)現(xiàn)是在任何C#程序中都是通用的。其測(cè)試用例如下所示: using QFramework; // 1.需要繼承QSingleton。 // 2.需要實(shí)現(xiàn)非public的構(gòu)造方法。 public class XXXManager : QSingleton<XXXManager> { private XXXManager() { // to do ... } } public static void main(string[] args) { XXXManager.Instance().xxxyyyzzz(); } 總結(jié) ??這個(gè)單例的模板是平時(shí)用得比較順手的工具了,其實(shí)現(xiàn)是在其他的框架中發(fā)現(xiàn)的,拿來直接用了。反射的部分可能會(huì)耗一些性能,但是只會(huì)執(zhí)行一次。在3d素材unity中可能會(huì)需要繼承MonoBehaviour的單例,因?yàn)楹芏嘤螒蚩赡軙?huì)只創(chuàng)建一個(gè)GameObject,用來獲取MonoBehaviour的生命周期,這些內(nèi)容會(huì)再下一講中介紹。 看完了這篇分享,是不是對(duì)3d素材unity游戲搭建有一定的了解了呢,如果能給您帶來一些幫助,匯寶盆萬(wàn)分榮幸!更多精彩可以進(jìn)群討論分享納金網(wǎng)匯寶盆交流⑤群 341024464。 本文轉(zhuǎn)載自網(wǎng)絡(luò),謝謝作者分享。
|