查看: 2163|回復(fù): 0
打印 上一主題 下一主題

[教程] 3d素材unity 游戲框架搭建 (二) 單例的模板

[復(fù)制鏈接]

Rank: 2

納金幣
48
精華
0
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2016-8-19 18:40:18 |只看該作者 |倒序?yàn)g覽
哈嘍,歡迎來到匯寶盆,首先非常感謝作者涼鞋的筆記分享這篇文章,上一篇文章中說到的manager of managers,其中每個manager都是單例的實(shí)現(xiàn),當(dāng)然也可以使用靜態(tài)類實(shí)現(xiàn),但是相比于靜態(tài)類的實(shí)現(xiàn),單例的實(shí)現(xiàn)更為通用,可以適用大多數(shù)情況。
如何設(shè)計(jì)這個單例的模板?
??先分析下需求,當(dāng)設(shè)計(jì)一個manager時候,我們希望整個程序只有一個該manager對象實(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;
    }
}
??如果一個游戲需要10個各種各樣的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 一個T???
            }
            return instance;
        }
    }
}
??為了可以被繼承,靜態(tài)實(shí)例和構(gòu)造方法都使用protect修飾符。以上的問題很顯而易見,那就是不能new一個泛型(39日補(bǔ)充:并不是不能new一個泛型,參考:new一個泛型的實(shí)例,編譯失敗了,為什么?-CSDN論壇-CSDN.NET-中國最大的IT技術(shù)社區(qū)),(45日補(bǔ)充:有同學(xué)說可以new一個泛型的實(shí)例,不過要求改泛型提供了public的構(gòu)造函數(shù),好吧,這里不用new的原因是,無法顯示調(diào)用private的構(gòu)造函數(shù))。因?yàn)榉盒捅旧聿皇且粋€類型,那該怎么辦呢?答案是使用反射。實(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)了。這個實(shí)現(xiàn)是在任何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é)
??這個單例的模板是平時用得比較順手的工具了,其實(shí)現(xiàn)是在其他的框架中發(fā)現(xiàn)的,拿來直接用了。反射的部分可能會耗一些性能,但是只會執(zhí)行一次。在3d素材unity中可能會需要繼承MonoBehaviour的單例,因?yàn)楹芏嘤螒蚩赡軙粍?chuàng)建一個GameObject,用來獲取MonoBehaviour的生命周期,這些內(nèi)容會再下一講中介紹
看完了這篇分享,是不是對3d素材unity游戲搭建有一定的了解了呢,如果能給您帶來一些幫助,匯寶盆萬分榮幸!更多精彩可以進(jìn)群討論分享納金網(wǎng)匯寶盆交流⑤群 341024464。
本文轉(zhuǎn)載自網(wǎng)絡(luò),謝謝作者分享。

本帖被以下淘專輯推薦:

  • · 教程|主題: 5, 訂閱: 1
分享到: QQ好友和群QQ好友和群 騰訊微博騰訊微博 騰訊朋友騰訊朋友 微信微信
轉(zhuǎn)播轉(zhuǎn)播0 分享淘帖1 收藏收藏1 支持支持0 反對反對0
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

手機(jī)版|納金網(wǎng) ( 閩ICP備2021016425號-2/3

GMT+8, 2024-10-31 07:23 , Processed in 0.093881 second(s), 30 queries .

Powered by Discuz!-創(chuàng)意設(shè)計(jì) X2.5

© 2008-2019 Narkii Inc.

回頂部