Unity 游戏框架搭建 (二) 单例的模板

上一篇文章中说到的manager of managers,其中每个manager都是单例的实现,当然也可以使用静态类实现,但是相比于静态类的实现,单例的实现更为通用,可以适用大多数情况。

如何设计这个单例的模板?
  先分析下需求,当设计一个manager时候,我们希望整个程序只有一个该manager对象实例,一般马上能想到的实现是这样的:
[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
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,那么以上这些代码要复制粘贴好多遍。重复的代码太多!!!想要把重复的代码抽离出来,怎么办?答案是引入泛型。实现如下:
[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;
         }
     }
}

  为了可以被继承,静态实例和构造方法都使用protect修饰符。以上的 问题 很显而易见,那就是不能new一个泛型(3月9日补充:并不是不能new一个泛型,参考:[new一个泛型的实例,编译失败了,为什么?-CSDN论坛-CSDN.NET-中国最大的IT技术社区]( http://bbs.csdn.net/topics/390911693 )),(4月5日补充:有同学说可以new一个泛型的实例,不过要求改泛型提供了public的构造函数,好吧,这里不用new的原因是,无法显示调用private的构造函数)。因为泛型本身不是一个类型,那该怎么办呢?答案是使用反射。实现如下:
[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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的构造方法
                 ConstructorInfo[] ctors = typeof (T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
                 // 从ctors中获取无参的构造方法
                 ConstructorInfo ctor = Array.Find(ctors, c => c.GetParameters().Length == 0);
                 if (ctor == null )
                     throw new Exception( "Non-public ctor() not found!" );
                 // 调用构造方法
                 instance = ctor.Invoke( null ) as T;
             }
 
             return instance;
         }
     }
}

以上就是最终实现了。这个实现是在任何C#程序中都是通用的。其测试用例如下所示:
[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
using QFramework; 
// 1.需要继承QSingleton。
// 2.需要实现非public的构造方法。
public class XXXManager : QSingleton<XXXManager> { 
     private XXXManager() {
         // to do ...
     }
}
 
 
public static void main( string [] args) 
{
     XXXManager.Instance().xxxyyyzzz();
}

总结
  这个单例的模板是平时用得比较顺手的工具了,其实现是在其他的框架中发现的,拿来直接用了。反射的部分可能会耗一些性能,但是只会执行一次。在中可能会需要继承MonoBehaviour的单例,因为很多游戏可能会只创建一个GameObject,用来获取MonoBehaviour的生命周期,这些内容会再下一讲中介绍:)
附:[我的框架地址]( https://github.com/liangxiegame/QFramework )


转载请注明地址:[凉鞋的笔记]( http://liangxiegame.com/ )
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值