开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:1532

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 1176|回复: 15

[凉鞋同学] Unity 游戏框架搭建 (十三) 无需继承的单例的模板

[复制链接]  [移动端链接]
排名
3913
昨日变化

13

主题

119

帖子

918

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
23
蛮牛币
906
威望
0
注册时间
2016-5-17
在线时间
284 小时
最后登录
2017-1-18

专栏作家

QQ
发表于 2016-11-26 18:07:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 liangxiegame 于 2016-11-26 18:08 编辑

  之前的文章中介绍的Unity 游戏框架搭建(二) 单例的模板 http://www.manew.com/thread-89635-1-1.html
和Unity游戏框架搭建(三) MonoBehaviour单例的模板http://www.manew.com/thread-89636-1-1.html有一些问题
存在的问题:
  • 只要继承了单例的模板就无法再继承其他的类。
  虽然单例继承其他类是比较脏的设计,但是难免会遇到不得不继承的时候。没有最好的设计,只有最合适的设计。
解决方案:
  • 首先实现单例的类从使用方式上应该不变,还是

[C#] 纯文本查看 复制代码
XXX.Instance.ABCFunc()
之前的单利的模板代码如下所示:

[C#] 纯文本查看 复制代码
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;
        }
    }
}

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

[C#] 纯文本查看 复制代码
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代码就变成这样了

[C#] 纯文本查看 复制代码
using QFramework;  
// 1.需要继承QSingleton。
// 2.需要实现非public的构造方法。
public class XXXManager : BaseManager {  
    private XXXManager() {
        // to do ...
    }
}


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

这样这个类就不是单例了,怎么办?
答案是通过C#的属性。

[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是什么?
和之前的单例的模板很相似,贴上代码自己品吧...

[C#] 纯文本查看 复制代码
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在使用时候多了一次函数调用,不过做中小型项目应该可以应付了。
介绍完毕,睡觉了。。。

附:我的框架地址:https://github.com/liangxiegame/QFramework
转载请注明地址:凉鞋的笔记 liangxiegame.com

评分

参与人数 2鲜花 +10 收起 理由
一剑飙血 + 5 赞一个!
yhy137084 + 5 赞一个!

查看全部评分


回复

使用道具 举报

3偶尔光临
282/300
排名
5793
昨日变化

1

主题

39

帖子

282

积分

Rank: 3Rank: 3Rank: 3

UID
15600
好友
0
蛮牛币
306
威望
0
注册时间
2014-2-25
在线时间
102 小时
最后登录
2016-12-19
发表于 2016-11-28 09:45:24 | 显示全部楼层
沙发,学习了~{:90:}{:90:}{:90:}{:90:}{:90:}

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1137/1500
排名
1106
昨日变化

1

主题

116

帖子

1137

积分

Rank: 6Rank: 6Rank: 6

UID
10743
好友
0
蛮牛币
1409
威望
0
注册时间
2013-12-20
在线时间
326 小时
最后登录
2017-1-3
发表于 2016-11-28 10:10:07 | 显示全部楼层
这不能算是严格的单例,这只能是基于约定的单例使用,但无法阻止其他开发人员直接调用目标类的无参构造函数。
[发帖际遇]: 狂飙的若羽 发帖时在路边捡到 2 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

排名
187
昨日变化

23

主题

384

帖子

2843

积分

Rank: 9Rank: 9Rank: 9

UID
10602
好友
11
蛮牛币
6013
威望
0
注册时间
2013-12-18
在线时间
784 小时
最后登录
2017-1-17

专栏作家认证开发者

发表于 2016-11-28 10:11:53 | 显示全部楼层
我一直关注你的框架,关于单例的东西,我之前也用过很多,其实想想,全局只要一个或者少数几个就好了,其他的都在这个单例类里面new一下就好了,这样也方便管理,单例多了,有时候,找起来也是麻烦事,也算是个人一点经验之谈

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1137/1500
排名
1106
昨日变化

1

主题

116

帖子

1137

积分

Rank: 6Rank: 6Rank: 6

UID
10743
好友
0
蛮牛币
1409
威望
0
注册时间
2013-12-20
在线时间
326 小时
最后登录
2017-1-3
发表于 2016-11-28 10:13:22 | 显示全部楼层
抱歉,刚才没有看仔细,是通过反射获取私有构造来做的。
但子类需要都实现一个私有的构造函数,可以理解为省略了私有静态单例字段和公有静态属性的相关代码。

值得参考,赞一个。

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1183/1500
排名
1146
昨日变化

0

主题

322

帖子

1183

积分

Rank: 6Rank: 6Rank: 6

UID
111260
好友
0
蛮牛币
3804
威望
0
注册时间
2015-6-30
在线时间
185 小时
最后登录
2017-1-18
发表于 2016-11-28 10:14:58 | 显示全部楼层
谢谢分享!

回复

使用道具 举报

排名
3683
昨日变化

5

主题

36

帖子

489

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
146655
好友
1
蛮牛币
152
威望
0
注册时间
2016-4-25
在线时间
198 小时
最后登录
2017-1-18
发表于 2016-11-28 10:33:52 | 显示全部楼层
感谢楼主分享!

回复

使用道具 举报

4四处流浪
411/500
排名
4935
昨日变化

0

主题

57

帖子

411

积分

Rank: 4

UID
8458
好友
0
蛮牛币
591
威望
0
注册时间
2013-11-19
在线时间
178 小时
最后登录
2017-1-13
发表于 2016-11-28 12:57:43 | 显示全部楼层
参考参考

回复

使用道具 举报

5熟悉之中
709/1000
排名
3132
昨日变化

3

主题

224

帖子

709

积分

Rank: 5Rank: 5

UID
68430
好友
0
蛮牛币
3412
威望
0
注册时间
2015-1-14
在线时间
186 小时
最后登录
2017-1-18
发表于 2016-11-28 15:09:48 | 显示全部楼层
不错,不错··

回复

使用道具 举报

7日久生情
1515/5000
排名
664
昨日变化

4

主题

147

帖子

1515

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
34678
好友
1
蛮牛币
3362
威望
0
注册时间
2014-7-16
在线时间
442 小时
最后登录
2017-1-18
发表于 2016-11-28 17:59:39 | 显示全部楼层
你这几篇单例模式的帖子都看了,设计模式不错,赞一个,但是也容易误导一些刚入的行的同学,有些新同学看到如此方便,估计会在项目中添加使用,这样对于项目可能会出现不能程度的麻烦,所以一句话,单例使用要慎重,鉴于的当前项目使用,而且单例不要过多,要不不好掌控,跟C#没有继承C++的多态一样,多了反而更繁琐。单例模式益用于中小型项目,而且不宜繁多。(个人意见)

回复 支持 反对

使用道具 举报

3偶尔光临
185/300
排名
9961
昨日变化

0

主题

98

帖子

185

积分

Rank: 3Rank: 3Rank: 3

UID
146677
好友
4
蛮牛币
743
威望
0
注册时间
2016-4-25
在线时间
31 小时
最后登录
2016-12-20
QQ
发表于 2016-11-28 20:15:39 | 显示全部楼层
不错的东西,顶一下,加油
[发帖际遇]: LiuBen 被钱袋砸中进医院,看病花了 2 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

7日久生情
1838/5000
排名
254
昨日变化

0

主题

70

帖子

1838

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
57557
好友
1
蛮牛币
4659
威望
0
注册时间
2014-11-25
在线时间
464 小时
最后登录
2017-1-17
QQ
发表于 2016-11-28 20:20:05 | 显示全部楼层
何必这么复杂,你让BaseManager继承单例,xxxManager继承BaseManager不就行了

回复 支持 反对

使用道具 举报

排名
3913
昨日变化

13

主题

119

帖子

918

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
23
蛮牛币
906
威望
0
注册时间
2016-5-17
在线时间
284 小时
最后登录
2017-1-18

专栏作家

QQ
 楼主| 发表于 2016-11-28 22:39:56 | 显示全部楼层
livin 发表于 2016-11-28 10:11
我一直关注你的框架,关于单例的东西,我之前也用过很多,其实想想,全局只要一个或者少数几个就好了,其他 ...

谢谢建议

回复 支持 反对

使用道具 举报

排名
3913
昨日变化

13

主题

119

帖子

918

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
23
蛮牛币
906
威望
0
注册时间
2016-5-17
在线时间
284 小时
最后登录
2017-1-18

专栏作家

QQ
 楼主| 发表于 2016-11-28 22:40:55 | 显示全部楼层
扯蛋超神 发表于 2016-11-28 20:20
何必这么复杂,你让BaseManager继承单例,xxxManager继承BaseManager不就行了

有道理,

回复 支持 反对

使用道具 举报

排名
3913
昨日变化

13

主题

119

帖子

918

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
23
蛮牛币
906
威望
0
注册时间
2016-5-17
在线时间
284 小时
最后登录
2017-1-18

专栏作家

QQ
 楼主| 发表于 2016-11-28 22:41:56 | 显示全部楼层
玄石流星 发表于 2016-11-28 17:59
你这几篇单例模式的帖子都看了,设计模式不错,赞一个,但是也容易误导一些刚入的行的同学,有些新同学看到 ...

谢谢建议,新同学看到你的建议应该会慎用的,哈哈哈

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表