上一篇文章中说到的manager of managers,其中每个manager都是单例的实现,当然也可以使用静态类实现,但是相比于静态类的实现,单例的实现更为通用,可以适用大多数情况。 如何设计这个单例的模板? 先分析下需求,当设计一个manager时候,我们希望整个程序只有一个该manager对象实例,一般马上能想到的实现是这样的: publicclassXXXManager{
privatestatic XXXManager instance = null;
private XXXManager { // to do ... }
publicstaticXXXManager(){ if (instance == null) { instance = new XXXManager(); } return instance; } } 如果一个游戏需要10个各种各样的manager,那么以上这些代码要复制粘贴好多遍。重复的代码太多!!!想要把重复的代码抽离出来,怎么办?答案是引入泛型。实现如下: using System; using System.Collections.Generic; using System.Text; using System.Reflection;
namespace QFramework { public abstract class QSingletonT where T : QSingletonT { protectedstatic T instance = null;
protectedQSingleton(){ }
publicstatic T Instance(){ if (instance == null) { // 如何new 一个T??? }
return instance; } } } 为了可以被继承,静态实例和构造方法都使用protect修饰符。以上的问题很显而易见,那就是不能new一个泛型(3月9日补充:并不是不能new一个泛型,参考:new一个泛型的实例,编译失败了,为什么?-CSDN论坛-CSDN.NET-中国最大的IT技术社区),(4月5日补充:有同学说可以new一个泛型的实例,不过要求改泛型提供了public的构造函数,好吧,这里不用new的原因是,无法显示调用private的构造函数)。因为泛型本身不是一个类型,那该怎么办呢?答案是使用反射。实现如下:using System; using System.Collections.Generic; using System.Text; using System.Reflection;
/// summary/// 1.泛型/// 2.反射/// 3.抽象类/// 4.命名空间/// /summarynamespace QFramework { public abstract class QSingletonT where T : QSingletonT { protectedstatic T instance = null;
protectedQSingleton(){ }
publicstatic 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) thrownew Exception("Non-public ctor() not found!"); // 调用构造方法 instance = ctor.Invoke(null) as T; }
return instance; } } } 以上就是最终实现了。这个实现是在任何C#程序中都是通用的。其测试用例如下所示: using QFramework; // 1.需要继承QSingleton。// 2.需要实现非public的构造方法。publicclass XXXManager : QSingletonXXXManager { privateXXXManager(){ // to do ... } }