凉鞋的笔记

努力 坚持,越幸运

嗨,我是凉鞋,我的乐趣是节省大家的时间。


Unity 游戏框架搭建 (十三) 无需继承的单例的模板

  之前的文章中介绍的Unity 游戏框架搭建 (二) 单例的模板Unity 游戏框架搭建 (三) MonoBehaviour单例的模板有一些问题。

存在的问题:
  • 只要继承了单例的模板就无法再继承其他的类。

  虽然单例继承其他类是比较脏的设计,但是难免会遇到不得不继承的时候。没有最好的设计,只有最合适的设计。

解决方案:
  • 首先实现单例的类从使用方式上应该不变,还是
 XXX.Instance.ABCFunc()

之前的单利的模板代码如下所示:

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 mInstance = null;

        protected QSingleton()
        {
        }

        public static T Instance
        {

            get {
                if (mInstance == 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!");
                    // 调用构造方法
                    mInstance = ctor.Invoke (null) as T;
                }

                return mInstance;
            }
        }

        public void Dispose()
        {
            mInstance = null;
        }
    }
}

按照以前的方式,如果想实现一个单例的代码应该是这样的:

using QFramework;  
// 1.需要继承QSingleton。
// 2.需要实现非public的构造方法。
public class XXXManager : QSingleton<XXXManager> {  
    private XXXManager() {
        // to do ...
    }
}


public static void main(string[] args)  
{
    XXXManager.Instance().xxxyyyzzz();
}

如果我想XXXManager继承一个BaseManager代码就变成这样了

using QFramework;  
// 1.需要继承QSingleton。
// 2.需要实现非public的构造方法。
public class XXXManager : BaseManager {  
    private XXXManager() {
        // to do ...
    }
}


public static void main(string[] args)  
{
    XXXManager.Instance().xxxyyyzzz();
}

这样这个类就不是单例了,怎么办?

答案是通过C#的属性。

using QFramework;  
// 1.需要继承QSingleton。
// 2.需要实现非public的构造方法。
public class XXXManager : BaseManager {  
    private XXXManager() {
        // to do ...
    }
    public static XXXManager Instance { 
        get {
            return QSingletonComponent<XXXManager>.Instance;
        }
    }
}


public static void main(string[] args)  
{
    XXXManager.Instance().xxxyyyzzz();
}

好了,又看到陌生的东西了,QSingletonComponent是什么?

和之前的单例的模板很相似,贴上代码自己品吧...

using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Reflection;

/// <summary>
///    组合方式实现单例子
/// </summary>
namespace QFramework {

    /// <summary>
    /// class是引用类型
    /// </summary>
    public class QSingletonComponent<T> where T : class
    {
        protected static T mInstance = null;

        public static T Instance
        {

            get {
                if (mInstance == 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!");
                    // 调用构造方法
                    mInstance = ctor.Invoke (null) as T;
                }

                return mInstance;
            }
        }

        public static void Dispose()
        {
            mInstance = null;
        }
    }
}

这样无法继承的问题就解决啦。

缺点是:相比于QSingleton,QSingletonComponent在使用时候多了一次函数调用,不过做中小型项目应该可以应付了。

介绍完毕,睡觉了。。。

附:我的框架地址
转载请注明地址:凉鞋的笔记
微信公众号:QWERTeam

最近的文章

Unity 游戏框架搭建 (十四) 优雅的QSignleton(零) QuickStart

QSingleton:   之前有几篇文章介绍过单例模板在Unity中的几种实现。之后又参考了其他的单例库的实现,借鉴(chao)了它们的优点,借鉴了哪里有声明原作者。 快速开始:   实现一个继承M…

Unity框架搭建, QSingleton继续阅读
更早的文章

Unity 游戏框架搭建 (十二) 简易AssetBundle打包工具(二)

  上篇文章中实现了基本的打包功能,在这篇我们来解决不同平台打AB包的问题。 本篇文章的核心api还是: BuildPipeline.BuildAssetBundles (outP…

Unity框架搭建继续阅读
comments powered by Disqus